使用结构化元素名称解析XML

时间:2016-09-04 10:41:50

标签: java xml xsd jaxb

我已经通过以下格式解析了一些第三方XML。测试的数量是无限的,但总是一个整数。

<tests>
    <test_1>
        <foo bar="baz" />
    </test_1>

    <test_2>
        <foo bar="baz" />
    </test_2>

    <test_3>
        <foo bar="baz" />
    </test_3>
</tests>

我目前正在使用XPath解析这个问题,但它有很多麻烦。有没有办法在XSD架构中表达这种XML风格并从中生成JAXB类。

据我所知,这是不可能的,唯一可能的是来自 how can I define an xsd file that allows unknown (wildcard) elements? <xs:any processContents="lax"/>技术,但是这允许任何内容,而不是<test_<integer>。我只想确认我没有错过一些XSD / JAXB技巧?

注意我希望XML的结构如此。我可能试图说服第三方改变。

<tests>
    <test id="1">
        <foo bar="baz" />
    </test>

    <test id="2">
        <foo bar="baz" />
    </test>

    <test id="3">
        <foo bar="baz" />
    </test>
</tests>

2 个答案:

答案 0 :(得分:1)

虽然有办法处理具有结构名称的元素,例如数字后缀,

确实应该修复基础XML设计 test_1应该是test)。

答案 1 :(得分:0)

为了完整性,这里是使用XSLT将<test_N>输入转换为<test id="N">样式的完整工作示例

<tests>
    <test_1>
        <foo bar="baz" />
    </test_1>
    <test_2>
        <foo bar="baz" />
    </test_2>
    <test_1234>
        <foo bar="baz" />
    </test_1234>
    <other>
        <foo></foo>
    </other>
</tests>

XSL

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[substring(name(), 1, 5) = 'test_']">
        <xsl:element name="test">
            <xsl:attribute name="id"><xsl:value-of select="substring(name(), 6, string-length(name()) - 5)" /></xsl:attribute>
            <xsl:copy-of select="node()" />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

代码

File input = new File("test.xml");
File stylesheet = new File("test.xsl");

StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
StringWriter writer = new StringWriter();
transformer.transform(new StreamSource(input), new StreamResult(writer));

System.out.println(writer);

输出

<?xml version="1.0" encoding="UTF-8"?>
<tests>
    <test id="1">
        <foo bar="baz"/>
    </test>

    <test id="2">
        <foo bar="baz"/>
    </test>

    <test id="1234">
        <foo bar="baz"/>
    </test>

    <other>
        <foo/>
    </other>
</tests>