-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathmanual-tweaking-output.html
383 lines (289 loc) · 19.3 KB
/
manual-tweaking-output.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
Copyright (C) 2005, 2006 Joe Walnes.
Copyright (C) 2006, 2007, 2008, 2021 XStream committers.
All rights reserved.
The software in this package is published under the terms of the BSD
style license a copy of which has been included with this distribution in
the LICENSE.txt file.
Created on 29. January 2005 by Joe Walnes
-->
<head>
<title>XStream - Tweaking the Output</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<!-- Google analytics -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-110973-2";
urchinTracker();
</script>
</head>
<body>
<div id="banner">
<a href="index.html"><img id="logo" src="logo.gif" alt="XStream"/></a>
</div>
<div id="center" class="Content2Column"> <!-- Content3Column for index -->
<div id="content">
<h1 class="FirstChild">Tweaking the Output</h1>
<p>Out of the box, XStream is able to serialize most objects without the need for custom mappings to be setup.
The XML produced is clean, however sometimes it's desirable to make tweaks to it. The most common use for this is
when using XStream to read configuration files and some more human-friendly XML is needed.</p>
<!-- ************ -->
<h1 id="Configuration">Modification by configuration</h1>
<p>A big part of the standard output of XStream can be configured. It is possible to set aliases for class types
and field names that are mapped to XML tag or attribute names. Objects that can be represented as simple string
value can be written as attributes. It is possible to omit fields or to flatten the structure for collections.</p>
<!-- .................. -->
<h2 id="Configuration_Aliases">Aliases</h2>
<p>Aliases offer a simple way to use different tag or attribute names in the XML. The simplest and most commonly
used tweak in XStream is to alias a fully qualified class to a shorter name. Another use case is a different field name
for a class member. Aliases can be set for following elements:</p>
<ul>
<li>Class types mapped to XML tags</li>
<li>Package names mapped to XML tags</li>
<li>Field names mapped to XML tags</li>
<li>Internal attributes names of XStream</li>
</ul>
<p>The bold elements in the following example are affected:</p>
<div class="Source XML"><pre><<b>cat</b>>
<<b>age</b>>4</<b>age</b>>
<<b>name</b>>Garfield</<b>name</b>>
<<b>owner</b> <b>type</b>="<b>StandardPerson</b>">
<<b>name</b>>Jon Arbuckle</<b>name</b>>
</<b>owner</b>>
</<b>cat</b>></pre></div>
<p>Have a look at the <a href="alias-tutorial.html">Alias Tutorial</a> for examples.</p>
<!-- .................. -->
<h2 id="Configuration_Attributes">Attributes</h2>
<p>XML is quite clumsy to read for fields in separate tags that can represent their content in a short single
string value. In such a case attributes can help to shorten the XML and increase readability:</p>
<div class="Source XML"><pre><cat <b>age="4" name="Garfield"</b>>
<owner class="StandardPerson" <b>name="Jon Arbuckle"</b>/>
</cat></pre></div>
<p>Attributes are also presented in the <a href="alias-tutorial.html">Alias Tutorial</a>.</p>
<!-- .................. -->
<h2 id="Configuration_OmitField">Omitted Fields</h2>
<p>For a proper deserialization XStream has to write the complete object graph into XML that is referenced by a
single object. Therefore XStream has to find a representation that contains all aspects to recreate the
objects.</p>
<p>However, some parts might be superfluous e.g. if a member field is lazy initialized and its content
can be easily recreated. In such a case a field can be omitted using
<a href="javadoc/com/thoughtworks/xstream/XStream.html">XStream.omitField(Class, String)</a>.</p>
<!-- .................. -->
<h2 id="Configuration_ImplicitCollection">Implicit Collections, Arrays and Maps</h2>
<p>Another use case are collections, arrays and maps. If a class has a field that is a one of those types, by
default all of its elements are embedded in an element that represents the container object itself. By
configuring the XStream with the
<a href="javadoc/com/thoughtworks/xstream/XStream.html#addImplicitCollection">XStream.addImplicitCollection()</a>,
<a href="javadoc/com/thoughtworks/xstream/XStream.html#addImplicitArray">XStream.addImplicitArray()</a>, and
<a href="javadoc/com/thoughtworks/xstream/XStream.html#addImplicitMap">XStream.addImplicitMap()</a> methods it
is possible to keep the elements directly as child of the class and the surrounding tag for the container object
is omitted. It is even possible to declare more than one implicit collection, array or map for a class, but
the elements must then be distinguishable to populate the different containers correctly at deserialization.</p>
<p>In the following example the Java type representing the farm may have two containers, one for cats and one
for dogs:</p>
<div class="Source XML"><pre><farm>
<<b>cat</b>>Garfield</<b>cat</b>>
<<b>cat</b>>Arlene</<b>cat</b>>
<<b>cat</b>>Nermal</<b>cat</b>>
<<b>dog</b>>Odie</<b>dog</b>>
</farm></pre></div>
<p>The container might be a Collection, Array, or even a Map. In the latter case a member field of the value
must have been defined, that is used as key in the deserialized map.</p>
<!-- .................. -->
<h2 id="Configuration_FieldOrder">Field order</h2>
<p>XStream is delivered with a lot of <a href="converters.html">converters</a> for standard types.
Nevertheless most objects are processed by converters based on reflection. They will write the fields of a
class in the sequence they are defined. It is possible to implement an algorithm for a different sequence or
use an implementation that allows to define the sequence for each type separately using a
<a href="javadoc/com/thoughtworks/xstream/converters/reflection/FieldKeySorter.html">FieldKeySorter</a>.
Similar functionality exists for Java Beans with the
<a href="javadoc/com/thoughtworks/xstream/converters/javabean/PropertySorter.html">PropertySorter</a>.</p>
<!-- .................. -->
<h2 id="Configuration_Format">Output Format</h2>
<p>XStream writes and reads XML by default. However, the I/O layer is separated from the model and you can
use implementations for other formats as well. A reader/writer pair is typically managed by a <a
href="javadoc/com/thoughtworks/xstream/io/HierarchicalStreamDriver.html">HierarchicalStreamDriver</a>. XStream
is delivering additional drivers for <a href="json-tutorial.html">JSON</a> and a compact binary format (see <a
href="javadoc/com/thoughtworks/xstream/io/binary/BinaryStreamDriver.html">BinaryStreamDriver</a>). There are
also drivers to write an object graph into a DOM structure instead of a text based stream (available for W3C
DOM, DOM4J, JDOM, XOM, and XPP DOM).</p>
<!-- ************ -->
<h1 id="Enhancing">Enhancing XStream</h1>
<p>Sometimes customization is simply not enough to tweak the output. Depending on the use case it is fortunate to
use specialized converters for own types, mapper implementations that control naming of things more globally or
use specialized writers to influence the complete output.</p>
<!-- .................. -->
<h2 id="Specialized_Converters">Specialized Converters</h2>
<p>Not all converters that are part of the XStream package are automatically registered. Some will only make
sense for special types, others have parameters to tweak the behaviour and are often most effective if
registered as local converter only. Most useful in the table of <a href="converters.html">converters</a> are
the JavaBeanConverter, NamedArrayConverter, NamedCollectionConverter, NamedMapConverter, ToStringConverter, and
ToAttributedValueConverter. Not to mention the separate Hibernate package of XStream.</p>
<p>As example can the ToAttributedValueConverter be used to define the owner's name directly as text value:</p>
<div class="Source XML"><pre><cat age="4" name="Garfield">
<owner class="StandardPerson"><b>Jon Arbuckle</b></>
</cat></pre></div>
<p>Attributes are also presented in the <a href="alias-tutorial.html">Alias Tutorial</a>.</p>
<!-- .................. -->
<h2 id="Enhancing_Converters">Custom Converters</h2>
<p>Sometimes the object to serialize contains fields or elements, that have no friendly representation for
human beings e.g. if a long value represents in reality a time stamp. In such cases XStream supports custom
converters for arbitrary types. Have a look at the <a href="converter-tutorial.html">Converter Tutorial</a>
for advanced possibilities. Note, that a custom converter is not different to one that is delivered by
XStream. It's simply your code.</p>
<!-- .................. -->
<h2 id="Enhancing_Mappers">Custom Mappers</h2>
<p>In case of global adjustments it can be helpful to implement an own mapper. A mapper is used to name things
and map between the name in the Java world to the name used in the XML representation. The alias mechanism
described above is implemented as such a mapper that can be configured. A typical use case is dropping all
prefixes for field names like underscores in the resulting XML or omitting the package part of class names.</p>
<p class="highlight">However, keep in mind that the algorithm must work in both directions to support deserialization.</p>
<!-- .................. -->
<h2 id="Enhancing_Name_Coder">Custom Name Coders</h2>
<p>Names used e.g. in XML for attributes and element tags might contain characters or character sequences that
violate the syntax of the output format. Instead of using different aliases for such names that depend on the
output format, you may use a NameCoder implementation that transforms an internally used name to an external
form. For XML we use e.g. a NameCoder that encodes '$' characters, while the one used in JSON performs no
operation at all.</p>
<p class="highlight">Again, keep in mind that the algorithm of the name coder must support encoding and
decoding of the names.</p>
<!-- .................. -->
<h2 id="Enhancing_Writer">Custom Writer</h2>
<p>A custom writer can be used to affect the output completely. XStream itself delivers solutions for different
use cases like the <a href="javadoc/com/thoughtworks/xstream/io/xml/CompactWriter.html">CompactWriter</a>
that does not insert any white spaces between the XML tags.</p>
<p>Another use case for such a writer is a wrapper to drop unwanted XML elements that XStream omits on its own.
Especially if the written XML is not used for deserialization it can be useful to ignore internal attributes by
a custom writer</p>
<!-- ************ -->
<h1 id="OwnCode">Tweaking the own implementation</h1>
<p>As shown, XStream can be configured and enhanced in multiple way, but sometimes it is easier to tweak the
implementation of the serialized classes:</p>
<ul>
<li>Declaring a field transparent will omit it automatically from the processing</li>
<li>Implementing a readResolve method that can be used to initialize additional fields</li>
<li>Usage of annotations</li>
</ul>
<!-- ************ -->
<h1 id="Processing">Preprocessing or postprocessing</h1>
<h2 id="Processing_XSLT">XML Transformations</h2>
<p>Never forget, you're dealing with XML! It is easy to transform XML with an XSLT. XStream is delivered with a SAXSource
implementation, that allows an XStream instance to be the source of a XML transformer.</p>
<h3>Example</h3>
<p>Look at the following stylesheet:</p>
<div class="Source XML"><pre>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/cat">
<xsl:copy>
<xsl:apply-templates select="mName"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet></pre></div>
<p>It is used here to remove the age of the cat on the fly (assuming XSLT is a string with the stylesheet above):</p>
<div class="Source Java"><pre>
XStream xstream = new XStream();
xstream.alias("cat", Cat.class);
TraxSource <b>traxSource</b> = new TraxSource(new Cat(4, "Garfield"), <b>xstream</b>);
Writer buffer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer(
new StreamSource(new StringReader(XSLT)));
transformer.transform(<b>traxSource</b>, new StreamResult(buffer));</pre></div>
<p>The result in the buffer:</p>
<div class="Source XML"><pre><cat>
<mName>Garfield</mName>
</cat></pre></div>
<h2 id="Processing_Copier">Format Conversion</h2>
<p>XStream is designed to transform Java objects into a specific format and recreate these objects again.
However, XStream's readers and writers are based on an event model that can be used easily to convert the pure
data between formats. XStream contains the <a href="javadoc/com/thoughtworks/xstream/io/copy/HierarchicalStreamCopier.html">HierarchicalStreamCopier</a>
tool that utilizes a reader and a writer of XStream to perform the conversion:</p>
<div class="Source Java"><pre>
HierarchicalStreamCopier copier = new HierarchicalStreramCopier();
HierarchicalStreamDriver binaryDriver = new BinaryDriver();
HierarchicalStreamDriver jsonDriver = new JettisonMappedXmlDriver();
// transform a org.dom4j.Document into a binary stream of XStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copier.copy(new Dom4JDriver.createReader(dom4JDocument), binaryDriver.createWriter(baos));
byte[] data = baos.getBytes();
// transform binary XStream data into JSON
StringWriter strWriter = new StringWriter();
copier.copy(binaryDriver.createReader(data), jsonDriver.createWriter(strWriter));
String json = strWriter.toString();
// transform JSON into XML:
strWriter = new StringWriter();
copier.copy(jsonDriver.createReader(new StringReader(json)), new PrettyPrintWriter(strWriter));
String xml = strWriter.toString();</pre></div>
<br/>
</div>
</div>
<div class="SidePanel" id="left">
<div class="MenuGroup">
<h1>Software</h1>
<ul>
<li><a href="index.html">About XStream</a></li>
<li><a href="news.html">News</a></li>
<li><a href="changes.html">Change History</a></li>
<li><a href="security.html">Security Aspects</a></li>
<li><a href="versioning.html">About Versioning</a></li>
</ul>
</div>
<div class="MenuGroup">
<h1>Evaluating XStream</h1>
<ul>
<li><a href="tutorial.html">Two Minute Tutorial</a></li>
<li><a href="license.html">License</a></li>
<li><a href="download.html">Download</a></li>
<li><a href="references.html">References</a></li>
<li><a href="benchmarks.html">Benchmarks</a></li>
<li><a href="https://www.openhub.net/p/xstream">Code Statistics</a></li>
</ul>
</div>
<div class="MenuGroup">
<h1>Using XStream</h1>
<ul>
<li><a href="architecture.html">Architecture Overview</a></li>
<li><a href="graphs.html">Object references</a></li>
<li class="currentLink">Tweaking the Output</li>
<li><a href="converters.html">Converters</a></li>
<li><a href="faq.html">Frequently Asked Questions</a></li>
<li><a href="mailing-lists.html">Mailing Lists</a></li>
<li><a href="issues.html">Reporting Issues</a></li>
</ul>
</div>
<div class="MenuGroup">
<h1>Javadoc</h1>
<ul>
<li><a href="javadoc/index.html">XStream Core</a></li>
<li><a href="hibernate-javadoc/index.html">Hibernate Extensions</a></li>
<li><a href="jmh-javadoc/index.html">JMH Module</a></li>
</ul>
</div>
<div class="MenuGroup">
<h1>Tutorials</h1>
<ul>
<li><a href="tutorial.html">Two Minute Tutorial</a></li>
<li><a href="alias-tutorial.html">Alias Tutorial</a></li>
<li><a href="annotations-tutorial.html">Annotations Tutorial</a></li>
<li><a href="converter-tutorial.html">Converter Tutorial</a></li>
<li><a href="objectstream.html">Object Streams Tutorial</a></li>
<li><a href="persistence-tutorial.html">Persistence API Tutorial</a></li>
<li><a href="json-tutorial.html">JSON Tutorial</a></li>
<li><a href="http://www.studytrails.com/java/xml/xstream/xstream-introduction.jsp">StudyTrails</a></li>
</ul>
</div>
<div class="MenuGroup">
<h1>Developing XStream</h1>
<ul>
<li><a href="how-to-contribute.html">How to Contribute</a></li>
<li><a href="team.html">Development Team</a></li>
<li><a href="repository.html">Source Repository</a></li>
<li><a href="https://travis-ci.org/x-stream/xstream/branches">Continuous Integration</a></li>
</ul>
</div>
</div>
</body>
</html>