Xml still occupy a more important position, such as micro-channel interface uses Xml defined message. This chapter focuses on the Xml create, edit, search, conversion, can be understood, this chapter is the use of dom4j, xstream is the most widely used among developers. This chapter is all a bit of operational Xml library.
0 Dom4j XStream brief
Xml word Dom4j focus on the operation performance library, Xstream is focused on the conversion between objects.
Dom4j
Dom4j To support XPath, XML Schema, large documents or stream of event-based document processing.
Dom4j provide build options for the document representation, that can be accessed in parallel by Dom4j-API function and standard underlying dom-API.
To achieve the above ambitious goal, Dom4j use interfaces and abstract base class and a method widely used in the JDK Collections class.
So Dom4j has extensive API, Dom4j more flexibility to take advantage of the above, the performance is impeccable.
Outstanding reputation of the Sun-JAXM, famous in Hibernate XML configuration files are parsed using Dom4j.
XStream
XStream based OXMapping Technical Note no other helper classes or map file, or if you used hibernate ORM framework mybatis like OXM not difficult to understand here.
Sequence may be XStream JavaBean into XML, moves or deserialize JavaBean XML, such XML serialization not cumbersome.
XStream JavaBean may be serialized or deserialized Json, easy to use.
No mapping file and the underlying model using xmlpull push parsing XML, high-performance, low memory footprint, combined with concise API, get started basically every minute thing.
XStream also can customize the type of conversion strategies and with a detailed error diagnosis, allows you to quickly locate the problem.
1 New Spring Boot Maven example projects
Note: IDEA is a development tool for
- File> New> Project, select the figure below
Spring Initializr
and then click [Next] Next - Fill
GroupId
(package name),Artifact
(project name) can be. Click Next
groupId = com.fishpro
artifactId = xmldom4j - The choice depends
Spring Web Starter
front tick. - Project name is set
spring-boot-study-xmldom4j
.
2 introduces dependence Pom
- dom4j-1.6.1 support for Java 1.4+
- dom4j-2.0.2 support for Java 5+
- dom4j-2.1.1 support for Java 8+
mvnrepository then use only 1.6.1 1.6.1
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jaxen/jaxen xpath解析的时候需要引入 jaxen包 否则会报错 java.lang.NoClassDefFoundError: org/jaxen/JaxenException-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream 支持xml转bean -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.11.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Code Example 3 Dom4j
3.1 Opening a remote xml
/**
* 解析远程 XML 文件
* @return Document xml 文档
* */
public static Document parse(URL url) throws DocumentException{
SAXReader reader = new SAXReader();
Document document =reader.read(url);
return document;
}
3.2 Creating an xml document
/**
* 创建一个 xml 文档
* */
public static Document createDocument() {
Document document = DocumentHelper.createDocument();
Element root = document.addElement("root");
Element author1 = root.addElement("author")
.addAttribute("name", "James")
.addAttribute("location", "UK")
.addText("James Strachan");
Element author2 = root.addElement("author")
.addAttribute("name", "Bob")
.addAttribute("location", "US")
.addText("Bob McWhirter");
return document;
}
3.3 traversal
System.out.println("====遍历================================");
//获取根节点
Element root = document.getRootElement();
// 遍历根节点下的子节点
for (Iterator<Element> it = root.elementIterator(); it.hasNext();) {
Element element = it.next();
// do something
System.out.println("根节下子节点名称:"+element.getName());
}
// 遍历子节点 author 下的子节点
for (Iterator<Element> it = root.elementIterator("feed"); it.hasNext();) {
Element foo = it.next();
// do something
System.out.println("author节点下节点名称:"+foo.getName());
}
// 后去根节点的属性
for (Iterator<Attribute> it = root.attributeIterator(); it.hasNext();) {
Attribute attribute = it.next();
// do something
System.out.println("根节下子节点属性:"+attribute.getName());
}
3.4 nodes using xpath get
System.out.println("================================================");
//使用 XPath 获取节点 获取多个节点
List<Node> list = document.selectNodes("//feed/entry");
for (Node node :list
) {
System.out.println("list node:"+node.getName());
}
Node node = document.selectSingleNode("//feed");
System.out.println("node:"+node.getName());
3.5 Save to File
//写到文件里面
Document document1=Dom4jUtils.createDocument();
FileWriter out = new FileWriter("foo.xml");
document1.write(out);
out.close();
3.6 XML text file transfer
Document xd=DocumentHelper.parseText(text);
3.7 Text-to-XML document object
String text = "<person> <name>James</name> </person>";
Document document = DocumentHelper.parseText(text);
3.8 XSLT transformation using XML
/**
* 使用XSLT转换XML
* */
public static Document styleDocument(Document document, String stylesheet) throws Exception {
TransformerFactory factory = TransformerFactory.newInstance();//实例化转换器工厂 TransformerFactory
Transformer transformer = factory.newTransformer(new StreamSource(stylesheet));// 创建一个转化格式对象
DocumentSource source = new DocumentSource(document); // XML 源对象
DocumentResult result = new DocumentResult(); //转换结果对象
transformer.transform(source, result);//转换操作
Document transformedDoc = result.getDocument();//获取转换后的文档
return transformedDoc;
}
Code Example 4 XStream
4.1 does not use an alias directly output xml
Blog.java (路径 src/main/java/com/fishpro/xmldom4j/domain/Blog.java)
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;
}
}
Part of the code
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!"));
//1.如果不设置别名呢
System.out.println(xstream.toXML(teamBlog));
/** 1.不设置别名输出
* <com.fishpro.xmldom4j.domain.Blog>
* <writer>
* <name>Guilherme Silveira</name>
* </writer>
* <entries>
* <com.fishpro.xmldom4j.domain.Entry>
* <title>first</title>
* <description>My first blog entry.</description>
* </com.fishpro.xmldom4j.domain.Entry>
* <com.fishpro.xmldom4j.domain.Entry>
* <title>tutorial</title>
* <description>Today we have developed a nice alias tutorial. Tell your friends! NOW!</description>
* </com.fishpro.xmldom4j.domain.Entry>
* </entries>
* </com.fishpro.xmldom4j.domain.Blog>
* */
4.2 alias direct output xml
Note the use of the definition Blog teamBlog above code. Note the effect of the output portion
//2.设置别名
xstream.alias("blog", Blog.class);
xstream.alias("entry", Entry.class);
System.out.println(xstream.toXML(teamBlog));
/** 2.设置别名
* <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>
* */
4.3 Substitute the name of the node
Note the use of the definition Blog teamBlog above code. Note the effect of the output portion
//3.writer 节点 转为 author节点
System.out.println("2.writer 节点 转为 author节点");
xstream.useAttributeFor(Blog.class, "writer");
xstream.aliasField("author", Blog.class, "writer");
System.out.println(xstream.toXML(teamBlog));
xstream.addImplicitCollection(Blog.class, "entries");
System.out.println(xstream.toXML(teamBlog));
/** 3. author 替代了 write
* <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.4 Entity object attributes as attributes of the node
Note the use of the definition Blog teamBlog above code. Note the effect of the output portion
//4.writer 作为 blog 的属性
System.out.println("4.作为blog的属性");
xstream.useAttributeFor(Blog.class, "writer");
xstream.registerConverter(new AuthorConverter());//作为blog的属性
System.out.println(xstream.toXML(teamBlog));
/** 4.writer 作为 blog 的属性
* <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>
* */
4.5 Use annotations @XStreamAlias
@XStreamAlias can be applied to similar, it can also be applied to the property name of the entity object Bean
This example uses the User and Address entities, their relationship is User can have multiple Address
User (路径 src/main/java/com/fishpro/xmldom4j/domain/User.java)
@XStreamAlias("user")
public class User {
@XStreamAlias("id")
private Integer userId;
@XStreamAlias("username")
private String username;
@XStreamImplicit
private List<Address> addresses;
public User(Integer userId,String username){
this.userId=userId;
this.username=username;
}
public User(Integer userId,String username,List<Address> addresses){
this.userId=userId;
this.username=username;
this.addresses=addresses;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
}
Address (路径 src/main/java/com/fishpro/xmldom4j/domain/Address.java)
@XStreamAlias("address")
public class Address {
private String street;
private String zipcode;
private String mobile;
public Address(String street,String zipcode,String mobile){
this.street=street;
this.zipcode=zipcode;
this.mobile=mobile;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
System.out.println("5.使用注解");
//5.使用注解
xstream.processAnnotations(User.class);
User msg = new User(1, "fishpro");
System.out.println(xstream.toXML(msg));
/** 使用注解 @XStreamAlias("user")
* <user>
* <id>1</id>
* <username>fishpro</username>
* </user>
* */
4.6 Use annotations @XStreamImplicit
Note the use of the definition Blog teamBlog above code. Note the effect of the output portion
//6.使用注解 子节点是列表
List<Address> addressList=new ArrayList<>();
addressList.add(new Address("江苏省南京市玄武大道1000号","201001","1801989098"));
addressList.add(new Address("江苏省南京市玄武大道1001号","201001","1811989098"));
msg = new User(1, "fishpro",addressList);
System.out.println(xstream.toXML(msg));
/** 6.使用注解 子节点是列表
* <user>
* <id>1</id>
* <username>fishpro</username>
* <address>
* <street>江苏省南京市玄武大道1000号</street>
* <zipcode>201001</zipcode>
* <mobile>1801989098</mobile>
* </address>
* <address>
* <street>江苏省南京市玄武大道1001号</street>
* <zipcode>201001</zipcode>
* <mobile>1811989098</mobile>
* </address>
* </user>
* */
4.9 Properties converter
When we encounter the date that may need to be converted into the desired format, we have to increase created the User object properties
private Calendar created = new GregorianCalendar();
Then the output will be above example, note the following created a multi-node
<user>
<id>1</id>
<username>fishpro</username>
<address>
<street>江苏省南京市玄武大道1000号</street>
<zipcode>201001</zipcode>
<mobile>1801989098</mobile>
</address>
<address>
<street>江苏省南京市玄武大道1001号</street>
<zipcode>201001</zipcode>
<mobile>1811989098</mobile>
</address>
<created>
<time>1565691626712</time>
<timezone>Asia/Shanghai</timezone>
</created>
</user>
Next, we create a new class converter
SingleValueCalendarConverter (path src / main / java / com / fishpro / xmldom4j / util / SingleValueCalendarConverter.java)
/**
* 日期转换器
* */
public class SingleValueCalendarConverter implements Converter {
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
Calendar calendar = (Calendar) source;
writer.setValue(String.valueOf(calendar.getTime().getTime()));
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(new Date(Long.parseLong(reader.getValue())));
return calendar;
}
public boolean canConvert(Class type) {
return type.equals(GregorianCalendar.class);
}
}
In the main operation example, the following changes in the created node
<user>
<id>1</id>
<username>fishpro</username>
<address>
<street>江苏省南京市玄武大道1000号</street>
<zipcode>201001</zipcode>
<mobile>1801989098</mobile>
</address>
<address>
<street>江苏省南京市玄武大道1001号</street>
<zipcode>201001</zipcode>
<mobile>1811989098</mobile>
</address>
<created>1565691762404</created>
</user>
4.10 deserialization
XStream xstream = new XStream();
xstream.alias("person", Person.class);//设置节点person的名称
xstream.alias("phonenumber", PhoneNumber.class);
Person joe = new Person("Joe", "Walnes");
joe.setPhone(new PhoneNumber(123, "1234-456"));
joe.setFax(new PhoneNumber(123, "9999-999"));
String xml = xstream.toXML(joe);//对象转 xml
System.out.println(xml);
/** 输出简单示例xml
* <person>
* <firstname>Joe</firstname>
* <lastname>Walnes</lastname>
* <phone>
* <code>123</code>
* <number>1234-456</number>
* </phone>
* <fax>
* <code>123</code>
* <number>9999-999</number>
* </fax>
* </person>
* */
Person newJoe = (Person)xstream.fromXML(xml);//xml 转 对象
problem:
Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/JaxenException
Need to introduce
<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
reference