原文地址:http://ahang8415.javaeye.com/blog/319902
1,存在的問題
設想我們的用戶端定義了一個用於XStream讀寫的XML檔案:
我們將設計一些模型類並配置XStream按照這個XML檔案格式執行讀寫操作。
<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>
2,模型:
首先,建立一個簡單的Blog對象:
package com.thoughtworks.xstream; public class Blog { private Author author; private List entries = new ArrayList(); public Blog(Author author) { this.author = author; } public void add(Entry entry) { entries.add(entry); } public List getContent() { return entries; } }
然後是一個帶有名字的作者對象:
package com.thoughtworks.xstream; public class Author { private String name; public Author(String name) { this.name = name; } public String getName() { return name; } }
具體的blog內容對象:
package com.thoughtworks.xstream; public class Entry { private String title, description; public Entry(String title, String description) { this.title = title; this.description = description; } }
雖然我們沒有建立getters/setters方法,但這並不影響XStream對XML->Object檔案的解析。
3,簡單的測試
首先初始化一個blog執行個體,然後使用XStream來序列化
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)); }
由該Blog執行個體解析出的XML檔案為:
<com.thoughtworks.xstream.Blog> <author> <name>Guilherme Silveira</name> </author> <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>
4,為類取別名首先我們來改變XStream對com.thoughtworks.xstream.Blog的輸出名稱。我們只想使用一個簡單的blog來取代。下面為Blog類建立一個別名:Xstream.alias("blog",Blog.class);同樣的,為Entry類建立一個別名:Xstream.alias("entry",Entry.class);好,到此輸出的XML變為:<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>
5,去掉entries標記
下面,我們將實施叫做"implicit collection"的過程(即取消標幟):所有的集合類型,都不需要顯示他的根標籤(root tag),你可以直接使用一個implicit collection去映射。
在我們的例子裡面,我們不希望出現entries標籤,只需要一個接一個的列出所有的entry標籤即可。
要做到這點,只需要簡單的調用XStream對象上的addImplicitCollection方法,就可以配置XStream取消對entries的輸出:
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)); } }注意addImplicitCollection方法的調用,需要描述在某個類上的某個成員變數不需要被顯示。
得到的結果基本上達到了要求:
<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>
7,為屬性添加別名
下一步是要把author成員變數設定為XML的屬性。要做到這點,我們需要告訴XStream將author屬性作為Blog類的"author"屬性。
xstream.useAttributeFor(Blog.class,"author");
現在留給我們一個問題,XStream怎麼講一個Author轉換成一個String對象讓他在Blog節點中以author屬性顯示?
只需要使用SimpleValeConverter並且實現我們自己的Author轉換器:
class AuthorConverter implements SingleValueConverter {
}
第一個需要實現的方法是告訴XStream該轉化器是用來轉換什麼類型的對象:
public boolean canConvert(Class type) {
return type.equals(Author.class);
}
接下來是將一個Author執行個體轉化成字串:
public String toString(Object obj) {
return ((Author) obj).getName();
}
最後是相反的工作:怎麼從一個字串中得到Author執行個體
public Object fromString(String name) {
return new Author(name);
}
最後,該轉化器看起來是這樣:
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);
}
}
然後將這個轉化器註冊到XStream:
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)); } }最後的輸出:
<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>
在這裡,useAttributeFor方法被其他幾個相似功能的方法重載,包括一個接受一個額外的字串(Class , String, String)的版本,該版本告訴XStream將該屬性建立為另一個別名,比如在這裡,如果使用useAttributeFor(Blog.class , "author", "auth")會將"author"屬性在XML中映射成"auth"屬性。