我正在对输入XML进行XSL转换,然后我需要在生成的文档中使用XPath提取一些值。但是,在使用XSL结果节点时,XPath表达式总是会返回null。 但是如果我将XSL结果文档存储在一个文件中,那么重新加载它。 XPath表达式返回相应的节点。
这是我的代码(实用功能已被删除,因为lisibility):
public class XmlTest {
@Test
public void testWithNativeJavaApi() throws Exception {
InputStream instream = resolveClasspathFile("xslt/xslt-test-transform-2.xsl");
StreamSource xsltSource = new StreamSource(instream);
DOMSource domSource = loadXmlFromClasspathFile("xslt/xslt-test-input-2.xml");
prettyPrint(domSource.getNode());
Transformer transformer = TransformerFactory.newInstance().newTransformer(xsltSource);
DOMResult domResult = new DOMResult();
transformer.transform(domSource, domResult);
Node node = domResult.getNode();
// Store then reload the file
// Uncommenting those 3 lines will make the test pass
// File xslOutputfile = new File("target", "xsl-ouput.xml");
// prettyPrint(node, new FileOutputStream(xslOutputfile));
// node = loadXmlFromInputStream(new FileInputStream(xslOutputfile)).getNode();
XPath xPathProcessor = XPathFactory.newInstance().newXPath();
XPathExpression xpathExpression = xPathProcessor.compile("/Message/Out/Personne/CodeCivilite");
System.out.println();
Node resultNode = (Node) xpathExpression.evaluate(node, XPathConstants.NODE);
if (resultNode != null) {
System.out.println(resultNode.getNodeName() + "=" + resultNode.getTextContent());
} else {
System.out.println("Node is null");
}
assertNotNull("XPath expression returned null node", resultNode);
assertEquals("CodeCivilite", resultNode.getNodeName());
assertEquals("M.", resultNode.getTextContent());
}
}
Juste评论或删除“// Store然后重新加载文件”下面的3行,测试将不再通过。
我完全陷入困境,欢迎任何帮助。
答案 0 :(得分:1)
默认情况下,DocumentBuilderFactory不使用命名空间,除非使用dbf.setNamespaceAware(true)。另一方面,XSL和TransformerFactory使用命名空间,因此生成的转换文档使用命名空间限定。
因此,当在XSL转换旁边调用时,XPathExpression应该使用命名空间。
XPath xPathProcessor = XPathFactory.newInstance().newXPath();
xPathProcessor.setNamespaceContext(new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
if(prefix.equals("t")) {
return "http://www.example.org/test";
} else {
return null;
}
}
@Override public String getPrefix(String namespaceURI) {
return null; // not used
}
@Override
public Iterator<?> getPrefixes(String namespaceURI) {
return null; // not used
}
});
XPathExpression xpathExpression = xPathProcessor.compile("/t:Message/t:Out/t:Personne/t:CodeCivilite");
System.out.println();
Node resultNode = (Node) xpathExpression.evaluate(node, XPathConstants.NODE);
引入临时文件,使用默认的DocumentBuilderFactory(不知道名称空间)重新加载,使非限定的XPATH表达式(没有名称空间)工作。
希望这很清楚:)
答案 1 :(得分:0)
我想知道解析文件是否给你一棵更短的树。尝试使用xpath表达式
//Message/Out/Personne/CodeCivilite
(前面的双斜线)没有文件i / o,看看是否有一个没有文件i / o的额外节点层。
答案 2 :(得分:0)
node = loadXmlFromInputStream(new FileInputStream(xslOutputfile))。getDocumentElement
();
是getDocumentElement()吗?
您是否可以打印重新加载的节点,看看您是否有预期的结果?