JaxB如何将列表的内容编组为单个标记

时间:2014-01-23 15:21:14

标签: java xml jaxb

我正在使用JAXB作为编组人员。

我有一个包含字符串列表和其他属性的对象。我想将列表内容编组为单独的标记。

我有代码List<String> items。如果我在列表中添加字符串“apple”,“banana”,“orange”,我想在编组时得到的xml是:

<items>
   <apple/>
   <banana/>
   <orange/>
</items>

这可行吗?或者,为了获得该结果,我如何更改对象?

(抱歉格式化,我无法做得更好)

1 个答案:

答案 0 :(得分:1)

我的建议

我的建议是不要这样做。相反,您的XML消息如下(这将使每个人都更容易处理您的XML):

<items>
   <item>apple</item>
   <item>banana</item>
   <item>orange</item>
</items>

你如何做到

好的,你决定不遵循我的建议:)。以下是如何做到这一点:

  1. 创建一个XmlAdapter,可以将String转换为org.w3c.dom.Element的实例,其名称等于String

    import javax.xml.bind.annotation.adapters.XmlAdapter;
    import javax.xml.parsers.*;
    import org.w3c.dom.*;
    
    public class StringAdapter extends XmlAdapter<Object, String> {
    
        private Document document;
    
        @Override
        public String unmarshal(Object v) throws Exception {
        Element element = (Element) v;
        return element.getTagName();
        }
    
        @Override
        public Object marshal(String v) throws Exception {
        return getDocument().createElement(v);
        }
    
        private Document getDocument() throws Exception {
        if(null == document) {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            document = db.newDocument();
        }
        return document;
        }
    
    }
    
  2. 注明List<String>字段/属性,@XmlJavaTypeAdapter指向您的XmlAdapter@XmlAnyElement注释。

     import java.util.*;
     import javax.xml.bind.annotation.*;
     import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
     @XmlRootElement
     public class Items {
    
        private List<String> items = new ArrayList<String>();
    
        @XmlAnyElement
        @XmlJavaTypeAdapter(StringAdapter.class)
        public List<String> getItems() {
        return items;
        }
    
      }
    
  3. 要提高效果,请确保您的XmlAdapter拥有Document的实例并在XMLAdapter上设置Marshaller以使其成为有状态以避免需要每次调用XmlAdapter时重新创建它。

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Items.class);
    
        Items items = new Items();
        items.getItems().add("apple");
        items.getItems().add("banana");
        items.getItems().add("orange");
    
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setAdapter(new StringAdapter());
        marshaller.marshal(items, System.out);
        }
    
    }