五、使用别名(Alias)
首先,有这样一段Java代码:
import java.util.ArrayList; import java.util.List; import com.thoughtworks.xstream.XStream; public class XStreamTest2 { 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)); } } 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; } } class Author { private String name; public Author(String name) { this.name = name; } public String getName() { return name; } } class Entry { private String title, description; public Entry(String title, String description) { this.title = title; this.description = description; } }
对于上面这段代码,现在我要将一个Blog对象转换成为XML字符串,产生的结果是:
<cn.tjpu.zhw.xml.Blog> <writer> <name>Guilherme Silveira</name> </writer> <entries> <cn.tjpu.zhw.xml.Entry> <title>first</title> <description>My first blog entry.</description> </cn.tjpu.zhw.xml.Entry> <cn.tjpu.zhw.xml.Entry> <title>tutorial</title> <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description> </cn.tjpu.zhw.xml.Entry> </entries> </cn.tjpu.zhw.xml.Blog>
但是,我要将一个Blog对象转换成为下面的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>
该怎么办呢?
这就需要用到别名转换方法了!
下面我们就一步步的调整代码:
1,给类起别名
需求:将节点cn.tjpu.zhw.xml.Blog、cn.tjpu.zhw.xml.Entry重命名为blog和entry
添加代码:
xstream.alias("blog", Blog.class); xstream.alias("entry", Entry.class);
即main方法如下:
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); System.out.println(xstream.toXML(teamBlog)); }
运行结果如下:
<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>
2,给字段其别名
需求:将writer节点重命名为author节点
添加代码:
xstream.aliasField("author", Blog.class, "writer");
即main方法为:
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.aliasField("author", Blog.class, "writer"); System.out.println(xstream.toXML(teamBlog)); }
运行结果如下:
<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>
3,使用隐式集合(Implicit Collection)
隐式集合:当你不想将一个集合的根节点呈现出来的时候,它就是一个隐式集合。
数组、Collection、Map都可以成为隐式集合。
需求:隐藏entries节点
添加代码:
xstream.addImplicitCollection(Blog.class, "entries");
则main方法如下:
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.aliasField("author", Blog.class, "writer"); xstream.addImplicitCollection(Blog.class, "entries"); System.out.println(xstream.toXML(teamBlog)); }
运行结果:
<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>
4,给XML属性起别名
需求:将writer节点,改成blog节点的authot属性
添加代码:
xstream.useAttributeFor(Blog.class, "writer");
即main方法如下:
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.useAttributeFor(Blog.class, "writer"); xstream.aliasField("author", Blog.class, "writer"); xstream.addImplicitCollection(Blog.class, "entries"); System.out.println(xstream.toXML(teamBlog)); }
但是运行的结果却是不是预想的那样:
<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>
可以看到,运行的结果根本就没有变化,为什么?
因为,还缺少一个转换器,XML节点的属性是一个String字符串,但是Author类不是字符串,这就需要一个转换器将Author对象转换成一个String对象、同时能够将String对象反转换为Author对象:
//定义一个转换器,如果使用,则需要在使用时注册到对应的XStream对象中 class AuthorConverter implements SingleValueConverter { /*该方法用于从Author对象中提取一个String字符串*/ public String toString(Object obj) { return ((Author) obj).getName(); } /*该方法用于从一个String字符串生成Author对象*/ public Object fromString(String name) { return new Author(name); } /*该方法告诉XStream对象,该转换器可以转换哪种类型的对象*/ public boolean canConvert(Class type) { return type.equals(Author.class); } }
新的main方法如下:
public class XStreamTest2 { 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); //设置XML节点的属性 xstream.useAttributeFor(Blog.class, "writer"); //注册转换器 xstream.registerConverter(new AuthorConverter()); xstream.aliasField("author", Blog.class, "writer"); xstream.addImplicitCollection(Blog.class, "entries"); 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>
5,使用包名别名
需求:有时候需要事项不同包里面的相同类名的节点之间的相互映射,这时就需要改变一下包名了
添加代码:
xstream.aliasPackage("org.thoughtworks", "cn.tjpu.zhw.xml");
即更改main方法:
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("org.thoughtworks", "cn.tjpu.zhw.xml"); System.out.println(xstream.toXML(teamBlog)); }
运行结果如下:
<org.thoughtworks.Blog> <writer> <name>Guilherme Silveira</name> </writer> <entries> <org.thoughtworks.Entry> <title>first</title> <description>My first blog entry.</description> </org.thoughtworks.Entry> <org.thoughtworks.Entry> <title>tutorial</title> <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description> </org.thoughtworks.Entry> </entries> </org.thoughtworks.Blog>