我正在为 VAST 文档构建一个解析器,这些文档是 XML 文档,有一个官方 XSD,有几个版本:https://github.com/InteractiveAdvertisingBureau/vast/tree/master
我需要能够解组传入的 XML,因此我使用
jaxb2-maven-plugin
生成了模型。
我需要能够处理传入的 XML,可能会或可能不会提到命名空间:我的问题是,当有命名空间时它可以工作,但当没有命名空间时它就不起作用。
以下https://stackoverflow.com/a/8717287/3067542和https://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Unmarshaller.html#unmarshalByDeclaredType,我知道有一个解决方法,因为我知道目标类类型,所以我可以强制解组到该类,无论是否有命名空间。
这是我的代码(也可以在 github 上找到)
JAXBContext jc = JAXBContext.newInstance(VAST.class);
Unmarshaller u = jc.createUnmarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(xmlString)));
JAXBElement<VAST> foo = u.unmarshal( doc, VAST.class);
return new CustomVast(foo.getValue());
运行测试时,我发现内部类未填充:
我错过了什么吗?使用
jaxb2-maven-plugin
生成类时是否需要设置一个额外的标志,以便它可以工作?
这个答案显然没有优化,但会提示您如何让它在 4.2 版本的命名空间和非命名空间 XML 上工作:
这里是
parseXml
的body方法
JAXBContext jc = JAXBContext.newInstance(VAST.class);
Unmarshaller u = jc.createUnmarshaller();
// should be optimized
TransformerFactory tf = TransformerFactory.newInstance();
StringWriter sw = new StringWriter();
URL urlXslt = VastParser.class.getClassLoader().getResource("xslt/vast_4.2.xslt");
File fileXslt = new File(urlXslt.toURI());
Transformer t = tf.newTransformer(new StreamSource(new FileInputStream(fileXslt)));
// transform original XML with XSLT to always add the namespace in the parsing
t.transform(new StreamSource(new StringReader(xmlString)), new StreamResult(sw));
// unmarshall transformed XML
JAXBElement<VAST> foo = u.unmarshal(new StreamSource(new StringReader(sw.toString())), VAST.class);
return new CustomVast(foo.getValue());
src/main/resources/xslt/vast_4.2.xslt
是:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|text()|comment()|processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- adds the xmlns part to the VAST element -->
<xsl:template match="/VAST">
<VAST xmlns="http://www.iab.com/VAST">
<xsl:apply-templates select="@*|node()"/>
</VAST>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这样,两个单元测试都适用于 4.2 部分。