-
Notifications
You must be signed in to change notification settings - Fork 9
/
alias-tutorial.html
440 lines (387 loc) · 19.2 KB
/
alias-tutorial.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
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
<!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 - Alias Tutorial</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">Alias Tutorial</h1>
<h2 id="problem">The problem</h2>
<p>Suppose that our client has defined a base XML file that we should make XStream read/write:</p>
<div class="Source Java"><pre><blog author="Guilherme Silveira">
<entry>
<title>first</title>
<description>My first blog entry.</description>
</entry>
<entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</entry>
</blog></pre>
<p>Based on the XML file above we shall create some model classes and configure XStream to write/read from this format.</p></div>
<div class="section">
<h2 id="model">The model</h2>
<p>First things first, the classes which shall represent our xml files are shown next, beginning with a simple Blog:</p>
<div class="Source Java"><pre>package com.thoughtworks.xstream;
public class Blog {
private Author writer;
private List entries = new ArrayList();
public Blog(Author writer) {
this.writer = writer;
}
public void add(Entry entry) {
entries.add(entry);
}
public List getContent() {
return entries;
}
}</pre></div>
<p>A basic author with name:</p>
<div class="Source Java"><pre>package com.thoughtworks.xstream;
public class Author {
private String name;
public Author(String name) {
this.name = name;
}
public String getName() {
return name;
}
}</pre></div>
<p>A blog entry contains a title and description:</p>
<div class="Source Java"><pre>package com.thoughtworks.xstream;
public class Entry {
private String title, description;
public Entry(String title, String description) {
this.title = title;
this.description = description;
}
}</pre></div>
<p>Although we did not create many getters/setters its up to you to create those you wish or those which make sense.</p></div>
<div class="section">
<h2 id="test">A simple test</h2>
<p>We can easily instantiate a new blog and use it with xstream:</p>
<div class="Source Java"><pre>public static void main(String[] args) {
Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
teamBlog.add(new Entry("first","My first blog entry."));
teamBlog.add(new Entry("tutorial",
"Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
XStream xstream = new XStream();
System.out.println(xstream.toXML(teamBlog));
}</pre></div>
<p>And the resulting XML is not so nice as we would want it to be:</p>
<div class="Source Java"><pre><com.thoughtworks.xstream.Blog>
<writer>
<name>Guilherme Silveira</name>
</writer>
<entries>
<com.thoughtworks.xstream.Entry>
<title>first</title>
<description>My first blog entry.</description>
</com.thoughtworks.xstream.Entry>
<com.thoughtworks.xstream.Entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</com.thoughtworks.xstream.Entry>
</entries>
</com.thoughtworks.xstream.Blog></pre></div></div>
<div class="section">
<h2 id="class_aliasing">Class aliasing</h2>
<p>The first thing we shall change is how XStream refers to the <b>com.thoughtworks.xstream.Blog</b> class.
We shall name it simply <i>blog</i>: let's create an alias called <i>blog</i> to the desired class:</p>
<div class="Source Java"><pre>xstream.alias("blog", Blog.class);</pre></div>
<p>Using the same idea, we can alias the 'Entry' class to 'entry':</p>
<div class="Source Java"><pre>xstream.alias("entry", Entry.class);</pre></div>
<p>The result now becomes:</p>
<div class="Source Java"><pre><blog>
<writer>
<name>Guilherme Silveira</name>
</writer>
<entries>
<entry>
<title>first</title>
<description>My first blog entry.</description>
</entry>
<entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</entry>
</entries>
</blog></pre></div></div>
<div class="section">
<h2 id="field_aliasing">Field aliasing</h2>
<p>Next we will change the name of the writer tag, but this time we have to use a field alias:</p>
<div class="Source Java"><pre>xstream.aliasField("author", Blog.class, "writer");</pre></div>
<p>The result now becomes:</p>
<div class="Source Java"><pre><blog>
<author>
<name>Guilherme Silveira</name>
</author>
<entries>
<entry>
<title>first</title>
<description>My first blog entry.</description>
</entry>
<entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</entry>
</entries>
</blog></pre></div></div>
<div class="section">
<h2 id="implicit">Implicit Collections</h2>
<p>Now let's implement what was called an <b>implicit collection</b>: whenever you have a collection which doesn't need
to display it's root tag, you can map it as an implicit collection.</p>
<p>In our example, we do not want to display the <b>entries</b> tag, but simply show the <b>entry</b> tags one after
another.</p>
<p>A simple call to the <b>addImplicitCollection</b> method shall configure XStream and let it know that we do not want to
write the <b>entries</b> tag as described above:</p>
<div class="Source Java"><pre>package com.thoughtworks.xstream;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
teamBlog.add(new Entry("first","My first blog entry."));
teamBlog.add(new Entry("tutorial",
"Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
XStream xstream = new XStream();
xstream.alias("blog", Blog.class);
xstream.alias("entry", Entry.class);
xstream.addImplicitCollection(Blog.class, "entries");
System.out.println(xstream.toXML(teamBlog));
}
}</pre></div>
<p>Pay attention to the <b>addImplicitCollection</b> method call: it describes which class and which member variable
shall assume the behaviour we described.</p>
<p>The result is almost what we wanted:</p>
<div class="Source Java"><pre><blog>
<author>
<name>Guilherme Silveira</name>
</author>
<entry>
<title>first</title>
<description>My first blog entry.</description>
</entry>
<entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</entry>
</blog></pre></div></div>
<p>Just as a side note: An array or a map can also be declared as implicit.</p>
<div class="section">
<h2 id="attributes">Attribute aliasing</h2>
<p>The next step is to set the <b>writer</b> member variable as an XML attribute. In order to do this, we shall tell
XStream to alias the <b>writer</b> field of the <b>Blog</b> class as an "author" attribute:</p>
<div class="Source Java"><pre> xstream.useAttributeFor(Blog.class, "writer");
xstream.aliasField("author", Blog.class, "writer");</pre></div>
<p>And now it leaves us with one problem: how does XStream converts an Author in a String so it can be written as a
XML tag attribute?</p>
<p>Attributes cannot be written for types that are handled by Converter implementations, we have to use a
<b>SingleValueConverter</b> and implement our own converter for the Author:</p>
<div class="Source Java"><pre>class AuthorConverter implements SingleValueConverter {
}</pre></div>
<p>The first method to implement tells XStream which types it can deal with:</p>
<div class="Source Java"><pre> public boolean canConvert(Class type) {
return type.equals(Author.class);
}</pre></div>
<p>The second one is used to extract a String from an Author:</p>
<div class="Source Java"><pre> public String toString(Object obj) {
return ((Author) obj).getName();
}</pre></div>
<p>And the third one does the opposite job: takes a String and returns an Author:</p>
<div class="Source Java"><pre> public Object fromString(String name) {
return new Author(name);
}</pre></div>
<p>Finally, the entire single value converter, responsible for converting Strings to Objects (Authors in this case) is:</p>
<div class="Source Java"><pre>class AuthorConverter implements SingleValueConverter {
public String toString(Object obj) {
return ((Author) obj).getName();
}
public Object fromString(String name) {
return new Author(name);
}
public boolean canConvert(Class type) {
return type.equals(Author.class);
}
}</pre></div>
<p>And let's register this converter:</p>
<div class="Source Java"><pre>public class Test {
public static void main(String[] args) {
Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
teamBlog.add(new Entry("first","My first blog entry."));
teamBlog.add(new Entry("tutorial",
"Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
XStream xstream = new XStream();
xstream.alias("blog", Blog.class);
xstream.alias("entry", Entry.class);
xstream.addImplicitCollection(Blog.class, "entries");
xstream.useAttributeFor(Blog.class, "author");
xstream.registerConverter(new AuthorConverter());
System.out.println(xstream.toXML(teamBlog));
}
}</pre></div>
<p>The result?</p>
<div class="Source Java"><pre><blog author="Guilherme Silveira">
<entry>
<title>first</title>
<description>My first blog entry.</description>
</entry>
<entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</entry>
</blog></pre></div>
</div>
<p class=highlight>You have to be aware, that attribute values normally have to be normalized by the XML parser as
required by the <a href="http://www.w3.org/TR/REC-xml/#AVNormalize">W3C spec</a>. Leading and trailing whitespaces
are normally removed as well as sequential ones! Therefore a deserialized string might differ from the value visible in
the XML representation.</p>
<div class="section">
<h2 id="packages">Package aliasing</h2>
<p>In the example above we have so far always used class aliases for the Blog and Entry type. Sometimes it is necessary to
map existing class types to others simply by changing the package name. Let us go back to the first attempt of our tutorial,
but this time we alias the package name instead of the individual classes:</p>
<div class="Source Java"><pre>public static void main(String[] args) {
Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
teamBlog.add(new Entry("first","My first blog entry."));
teamBlog.add(new Entry("tutorial",
"Today we have developed a nice alias tutorial. Tell your friends! NOW!"));
XStream xstream = new XStream();
xstream.aliasPackage("my.company", "org.thoughtworks");
System.out.println(xstream.toXML(teamBlog));
}</pre></div>
<p>And the resulting XML contains now the classes with the aliased package names:</p>
<div class="Source Java"><pre><my.company.xstream.Blog>
<author>
<name>Guilherme Silveira</name>
</author>
<entries>
<my.company.xstream.Entry>
<title>first</title>
<description>My first blog entry.</description>
</my.company.xstream.Entry>
<my.company.xstream.Entry>
<title>tutorial</title>
<description>
Today we have developed a nice alias tutorial. Tell your friends! NOW!
</description>
</my.company.xstream.Entry>
</entries>
</my.company.xstream.Blog></pre></div>
<p>Please recognize that the package name alias works also for sub packages in this example.</p>
</div>
<div class="section">
<h2 id="summary">Summing up</h2>
<p>To recap:</p>
<ul>
<li>You can use class aliases to change tag names</li>
<li>You can use field aliases to change tag names</li>
<li>You can use package aliases to change tag names</li>
<li>Fields can be written as attributes if the field type is handled by a SingleValueConverter</li>
</ul>
<p>Don't forget to read the <a href="converter-tutorial.html">converter tutorial</a> to see other type of converters that you can create using XStream.
Or look into the condensed overview how to configure XStream to <a href="manual-tweaking-output.html">tweak the output</a>.</p>
</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><a href="manual-tweaking-output.html">Tweaking the Output</a></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 class="currentLink">Alias Tutorial</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>