代码之家  ›  专栏  ›  技术社区  ›  Nikolaus Trixner

JAXB/XSD:Number而不是Element name

  •  0
  • Nikolaus Trixner  · 技术社区  · 5 年前

    我必须从一个xml文件创建Java对象(在转换之前我不能编辑),所以我认为最好创建一个XSD,然后通过JAXB对文件进行解组。

    <parent-element>
        <id-00001>...</id-00001>
        <id-00002>...</id-00002>
        ...
    </parent-element>
    

    所以基本上我有一个xml元素列表,元素的“名称”是列表中的顺序。在这些列表中,每个元素的数量可能是无限的。 是否可以用JAXB来解组,或者我必须使用XML读取器并循环遍历元素?“id-XXXXX”元素在内部的格式都是相同的,因此如果它的格式是“”的话,就可能没有任何问题。

    提前谢谢!

    0 回复  |  直到 5 年前
        1
  •  1
  •   Michał Ziober    5 年前

    我想你的 XML 有效载荷如下:

    <root>
        <parent-element>
            <id-00001>value 1</id-00001>
            <id-00002>value 2</id-00002>
        </parent-element>
    </root>
    

    要读取具有动态名称的节点,我们需要编写自定义适配器( javax.xml.bind.annotation.adapters.XmlAdapter

    @XmlRootElement(name = "root")
    @XmlAccessorType(XmlAccessType.FIELD)
    class Root {
    
        @XmlElement(name = "parent-element")
        @XmlJavaTypeAdapter(IdsXmlAdapter.class)
        private MultiItemList list;
    
        // getters, setters, toString
    }
    
    class MultiItemList {
    
        private List<String> ids;
    
        // getters, setters, toString
    }
    

    对于以上 XML格式 POJO 模型自定义适配器可能如下所示:

    class IdsXmlAdapter extends XmlAdapter<Object, MultiItemList> {
    
        @Override
        public MultiItemList unmarshal(Object v) {
            Element element = (Element) v;
            NodeList childNodes = element.getChildNodes();
            List<String> ids = new ArrayList<>(childNodes.getLength());
            for (int i = 0; i < childNodes.getLength(); i++) {
                Node item = childNodes.item(i);
                if (item.getNodeName().equals("#text")) {
                    continue;
                }
                ids.add(item.getTextContent());
            }
    
            MultiItemList multiItemList = new MultiItemList();
            multiItemList.setIds(ids);
            return multiItemList;
        }
    
        @Override
        public Object marshal(MultiItemList v) throws Exception {
            return null; // Implement if needed
        }
    }
    

    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    import java.io.File;
    import java.io.FileReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class JaxbApp {
    
        public static void main(String[] args) throws Exception {
            File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
    
            JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
    
            Object unmarshal = jaxbContext.createUnmarshaller().unmarshal(new FileReader(xmlFile));
            System.out.println(unmarshal);
        }
    }
    

    印刷品:

    Root{list=Root{ids=[value 1, value 2]}}
    

    XmlAdapter<Element, MultiItemList> 适配器由于异常:

    Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
    org.w3c.dom.Element is an interface, and JAXB can't handle interfaces.
        this problem is related to the following location:
            at org.w3c.dom.Element
    

    另见:

        2
  •  1
  •   martidis    5 年前

    @XmlAnyElement 还有一个适配器。 @XmlAnyElement公司

    例如,使用下面给出的xml:

    <parent-element>
        <id-00001>value 1</id-00001>
        <id-00002>value 2</id-00002>
    </parent-element>
    

    你的根可能是这样的:

    @XmlRootElement(name = "parent-element")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Root {
    
        @XmlAnyElement
        @XmlJavaTypeAdapter(MyAdapter.class)
        private List<String> varyingElements;
    
    }
    

    你的适配器是这样的:

    public class MyAdapter extends XmlAdapter<Element, String> {
    
        @Override
        public Element marshal(String arg0) throws Exception {
            // do what you must
            return null;
        }
    
        @Override
        public String unmarshal(Element element) throws Exception {
            return element.getChildNodes().item(0).getNodeValue();
        }
    
    }
    

    org.w3c.dom.Element