Small modification of Jaxb's xml header

 

Preface:
  It is also in actual work that jaxb is used to realize the mapping and conversion of xml to java objects. In practical applications, I have also encountered some interesting and fun things, which should be recorded.
  This article mainly explains how jaxb generates the agreed xml message The idea of ​​​​the implementation of the header is relatively small, and the method is a bit tricky, so it leads to a little confusion when taking the title of the blog post, ^_^.

 

Phenomenon:
  Let's first define a simple java class and use it to generate its corresponding xml content.

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement(name="root")
    public static class TNode {

        @XmlElement(name="key", required = true)
        private String key;

        @XmlElement(name="value", required = true)
        private String value;

    }


    public static void main(String[] args) {
        TNode obj = new TNode("key_1", "val_1");
        try {
            JAXBContext jc = JAXBContext.newInstance(TNode.class);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);

            System.out.println(writer.toString());
        } catch (JAXBException e) {
            e.printStackTrace ();
        }
    }

  Note: This is a simple entity class, and the corresponding jaxb code to generate xml The
  specific generation results are as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <key>key_1</key>
    <value>val_1</value>
</root>

  In the default xml header, there is one more standalone="yes" than the common one . Is there a way to remove this little tail?

 

Try the idea:
  The Marshaller class defines a lot of properties, let's first see if there is any configuration related to the header.

public interface Marshaller {

    // *) Specify the encoding mode
    public static final String JAXB_ENCODING = "jaxb.encoding";

    // *) Specify whether to support indentation and line breaks when outputting
    public static final String JAXB_FORMATTED_OUTPUT = "jaxb.formatted.output";

    /**
     * The name of the property used to specify the xsi:schemaLocation
     * attribute value to place in the marshalled XML output.
     */
    public static final String JAXB_SCHEMA_LOCATION = "jaxb.schemaLocation";

    /**
     * The name of the property used to specify the
     * xsi:noNamespaceSchemaLocation attribute value to place in the marshalled
     * XML output.
     */
    public static final String JAXB_NO_NAMESPACE_SCHEMA_LOCATION
        = "jaxb.noNamespaceSchemaLocation";

    // *) Whether to generate a header
    public static final String JAXB_FRAGMENT = "jaxb.fragment";

}

  It's a little disappointing that there are only two information related to the header, JAXB_ENCODING controls the encoding , JAXB_FRAGMENT controls the visibility of the header, and there is no configuration item for standalone visibility. It seems that this way is not feasible.

 

Solution:
  I originally thought that jaxb provided some listeners to achieve this function, but I haven't studied it yet. Inadvertently, I saw a netizen write a code to output xml, and suddenly thought that he might have encountered the same problem, but he didn't explain why The purpose of doing this is written out.
  We re-modify the code that generates xml:

    public static void main(String[] args) {
        TNode obj = new TNode("key_1", "val_1");
        try {
            JAXBContext jc = JAXBContext.newInstance(TNode.class);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            // 1) Hide the generation of message headers, Marshaller.JAXB_FRAGMENT defaults to false
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

            StringWriter writer = new StringWriter();
            // 2) custom build
            writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
            marshaller.marshal(obj, writer);

            System.out.println(writer.toString());
        } catch (JAXBException e) {
            e.printStackTrace ();
        }
    }

  Note: Two points, 1. Activate JAXB_FRAGMENT to true, hide jaxb to automatically generate xml header. 2. Customize output header information
  Test it, the results are as follows:

<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <key>key_1</key>
    <value>val_1</value>
</root>

 

Summary:
  This can also be regarded as a blog hydrology, here is a study note, and I want to learn more about the performance optimization of jaxb and the internal implementation mechanism.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325208338&siteId=291194637