Spring Boot Dom4j XStream operation using Xml

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

  1. File> New> Project, select the figure below Spring Initializrand then click [Next] Next
  2. Fill GroupId(package name), Artifact(project name) can be. Click Next
    groupId = com.fishpro
    artifactId = xmldom4j
  3. The choice depends Spring Web Starterfront tick.
  4. 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

Guess you like

Origin www.cnblogs.com/fishpro/p/spring-boot-study-xml.html