使用jaxb处理带有可选内部标记和值的xml

时间:2017-07-23 19:48:48

标签: java xml jaxb

我有一个var theArray = [ [1, 2, 3], [3, 2, 1], [1, 2, 3], [1, 2, 1] ]; var not = [1,3,1,3]; theArray.forEach((array, index) => { array.forEach((digit, numIndex) => { if(theArray[index +1] && theArray[index + 1][numIndex] && theArray[index + 1][numIndex] == 3 && digit == 1 && !theArray.map(arr => arr[index +1]) .every((el, i) => el === not[i]) && !theArray.map(arr => arr[index +1]) .every((el, i) => el === not.slice(0).reverse()[i])) { array[numIndex] = "foo" } else if(theArray[index - 1] && theArray[index - 1][numIndex] && theArray[index -1][numIndex] == "foo" && digit == 3) { if (!theArray.map(arr => arr[index -1]) .every((el, i) => el === not[i]) && !theArray.map(arr => arr[index -1]) .every((el, i) => el === not.slice(0).reverse()[i])) array[numIndex] = "bar" } }) }); console.log(theArray);文件,看起来像这样

xml

基本上,节点<console-menu-entry index="2" text="Print Hello World"> <console-menu-entry index="1" text="Print Hello"> print 'Hello' </console-menu-entry> <console-menu-entry index="2" text="Print World"> print 'World' </console-menu-entry> </console-menu-entry> 可能在其中包含标签或某些文本值。

如何使用<console-menu-entry>处理它?当我这样做时,它失败了

jaxb

错误。

我的班级看起来像这样

If a class has @XmlElement property, it cannot have @XmlValue property.

P.S。使用@XmlRootElement(name="console-menu-entry") @XmlAccessorType(XmlAccessType.FIELD) @ToString public @Data class XmlConsoleMenuEntry { @XmlAttribute private String index; @XmlAttribute private String text; @XmlValue private String value; @XmlElement(name="console-menu-entry") private List<XmlConsoleMenuEntry> entries; } 不是必需的,所以如果有使用其他库的方法,我愿意接受建议。

1 个答案:

答案 0 :(得分:1)

我建议使用JAXB但是来自另一端。尝试使用xsd架构。这种方法有许多优点:

  1. 开发XSD可让您更深入地了解数据模型,检测可能的缺陷并更清晰地查看数据结构。
  2. 你可以use XSD to generate the parser帮助你用几行代码解析你的xml(满足那个模型)
  3. 您可以使用XSD创建xml文件(所有现代IDE都在代码辅助机制中集成XSD数据),以便您从IDE获得有关哪个元素适合您的数据模型在特定位置的建议,该属性是否需要一个特定的元素(甚至哪个值适合那个attrubute)和许多其他有用的东西
  4. 下面是xsd模式的示例,它将允许您生成解析您的示例的解析器(您应该只为您的xml元素提供适当的命名空间)

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               targetNamespace="http://some.your.schema"
               xmlns:tns="http://some.your.schema"
               elementFormDefault="qualified">
    
        <xs:complexType name="ConsoleMenuEntry" mixed="true" >
            <xs:sequence>
                <xs:element ref="tns:console-menu-entry" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="index" type="xs:integer" use="required"/>
            <xs:attribute name="text" type="xs:string" use="required"/>
        </xs:complexType>
    
        <xs:element name="console-menu-entry" type="tns:ConsoleMenuEntry"/>
    
    </xs:schema>
    

    您现在可以生成解析器文件(Windows示例)

    "%JAVA_HOME%\bin\xjc" -d ../src -p your.app.generated test.xsd
    

    其中-d ../src指定解析器类所在的硬盘驱动器上的路径,-p your.app.generated指定生成的解析器类的包,test.xsd是模式文件名

    以下是test.xml的示例:

    <?xml version="1.0" encoding="UTF-8" ?>
    <console-menu-entry xmlns="http://some.your.schema" index="1" text="Some new text">
        <console-menu-entry index="1" text="some other text">
            sdfsdkljf
        </console-menu-entry>
        <console-menu-entry index="2" text="some other text"/>
    </console-menu-entry>
    

    解析它的代码:

    public class Main {
    
        public static void main(String[] args) throws JAXBException {
    
            JAXBContext jc = JAXBContext.newInstance(ObjectFactory.class);
            ConsoleMenuEntry rootEntry = ((JAXBElement<ConsoleMenuEntry>) jc.createUnmarshaller().unmarshal(new File("PATH_TO_FILE\\test.xml"))).getValue();
            processMenuEntry(rootEntry);
        }
    
        private static void processMenuEntry(ConsoleMenuEntry menuEntry) {
            System.out.println("Index (attr) = " + menuEntry.getIndex() + ", Text (attr) = '" + menuEntry.getText() + "'");
    
            for (Serializable element : menuEntry.getContent()) {
                if (element instanceof JAXBElement) {
                    processMenuEntry(((JAXBElement<ConsoleMenuEntry>) element).getValue());
                } else if (element instanceof String) {
                    String innerText = element.toString().trim();
                    if (innerText.length() > 0) {
                        System.out.println("Inner text: '" + innerText);
                    }
                }
            }
        }
    }