我读过XPath - how to select text并认为我有一般的想法。但是,像往常一样,XPath抬起头来,发出嘶嘶声,然后匆匆离开,找到最近被细菌滋生的尿壶淹死。
我有一个JPA orm.xml文件。它看起来像这样:
<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
version="2.0">
<persistence-unit-metadata>
<persistence-unit-defaults>
<schema>test</schema>
<catalog>test</catalog>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>
我认为,以下XPath表达式应该从<schema>
元素中选择文本:
/entity-mappings/persistence-unit-metadata/persistence-unit-defaults/schema/text()
但是使用Java的XPath实现,却没有。
更具体地说,以下代码在最后一行失败(使用JUnit断言)。 text
变量的值是空字符串。
// Find the file: URL to the orm.xml I mentioned above.
final URL ormUrl = Thread.currentThread().getContextClassLoader().getResource("META-INF/orm.xml");
assertNotNull(ormUrl);
final XPathFactory xpf = XPathFactory.newInstance();
assertNotNull(xpf);
final XPath xpath = xpf.newXPath();
assertNotNull(xpath);
final XPathExpression expression = xpath.compile("/entity-mappings/persistence-unit-metadata/persistence-unit-defaults/schema/text()");
assertNotNull(expression);
final String text = expression.evaluate(new InputSource(ormUrl.openStream()));
assertEquals("test", text);
这似乎让人怀疑我对XPath表达式的理解是什么。围绕着,我想看看一个简单的"/"
是否会选择根元素。幸运的是,这返回了非null
NodeList
,但NodeList
为空。我真的不想找到Java XPath支持的作者并将它们串起来,但是如果不采取这种行动,那就太难了。
请一劳永逸地帮我拍摄XPath。感谢。
答案 0 :(得分:4)
问题是XML声明了一个默认命名空间
xmlns="http://java.sun.com/xml/ns/persistence/orm"
在XPath表达式中,您没有提供相应的命名空间上下文。有关如何使用命名空间上下文的详细信息,请参阅this link。那里有很多细节,但总的来说,你必须编写自己的javax.xml.namespace.NamespaceContext
实现,它允许XPath处理器将名称空间前缀映射到URI。在您的情况下,您必须提供默认命名空间到适当URI的映射。