Jaxb對xml報文頭的小修小改

前言:
  也是在實際工作中, 藉助jaxb來實現xml到java對象的映射轉換. 在實際應用中, 也遇到了一些有趣好玩的東西, 權當記錄下來. 
  本文主要講解jaxb如何生成約定的xml報文頭的實現思路, 點比較小, 而且方法有點trick, 因此導致取博文標題的時候, 也有些小迷茫, ^_^.

 

現象:
  我們先來定義一個簡單的java類, 並用於生成其對應的xml內容.

@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();
        }
    }

  注: 這是簡單的實體類, 以及對應的jaxb生成xml的代碼
  具體的生成結果如下:

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

  在默認的xml報文頭裏, 比常見的多了一個standalone="yes" , 有沒有辦法去掉這個小尾巴呢?

 

嘗試思路: 
  Marshaller類定義了很多屬性, 我們先來看一下有沒有報文頭相關的配置.

public interface Marshaller {

    // *) 指定編碼模式
    public static final String JAXB_ENCODING = "jaxb.encoding";

    // *) 指定輸出時, 是否支持縮進和換行
    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";

    // *) 是否生成報文頭
    public static final String JAXB_FRAGMENT = "jaxb.fragment";

}

  讓人有點小失望, 裏面涉及報文頭的信息, 只有兩個, JAXB_ENCODING控制編碼JAXB_FRAGMENT控制報文頭的可見性, 對standalone的可見性沒有配置項. 看來這條路是行不通的.

 

解決思路:
  本來覺得jaxb提供了一些listener是可以實現這個功能, 不過還沒研究. 無意中, 看到網友寫了一段輸出xml的代碼, 突然想到他或許也遇到了同樣的問題, 只是沒把爲什麼這樣做的目的寫出來.
  我們重新修改下生成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) 隱去報文頭的生成, Marshaller.JAXB_FRAGMENT默認爲false
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

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

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

  注: 兩個要點, 1. 激活JAXB_FRAGMENT爲true, 隱去jaxb自動生成xml報文頭. 2. 自定義輸出報文頭信息
  測試一下, 結果如下:

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

 

原文連接: http://www.mamicode.com/info-detail-2280778.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章