命名空间上下文和将命名空间与 XPath 结合使用
解析在 Java 中包含命名空间的 xpath 似乎需要使用对象,将前缀映射到命名空间 url,反之亦然。但是,除了自己实现它之外,我找不到其他机制。这似乎有悖常理。NamespaceContext
NamespaceContext
问题:有没有简单的方法可以从文档中获取,或者创建一个,或者如果没有,完全放弃前缀并使用完全限定的名称指定xpath?NamespaceContext
解析在 Java 中包含命名空间的 xpath 似乎需要使用对象,将前缀映射到命名空间 url,反之亦然。但是,除了自己实现它之外,我找不到其他机制。这似乎有悖常理。NamespaceContext
NamespaceContext
问题:有没有简单的方法可以从文档中获取,或者创建一个,或者如果没有,完全放弃前缀并使用完全限定的名称指定xpath?NamespaceContext
可以在不编写自己的类的情况下获取 NamespaceContext 实例。它的类使用页面显示你可以使用javax.xml.stream包来获得一个。
String ctxtTemplate = "<data xmlns=\"http://base\" xmlns:foo=\"http://foo\" />";
NamespaceContext nsContext = null;
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader evtReader = factory
.createXMLEventReader(new StringReader(ctxtTemplate));
while (evtReader.hasNext()) {
XMLEvent event = evtReader.nextEvent();
if (event.isStartElement()) {
nsContext = ((StartElement) event)
.getNamespaceContext();
break;
}
}
System.out.println(nsContext.getNamespaceURI(""));
System.out.println(nsContext.getNamespaceURI("foo"));
System.out.println(nsContext
.getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE));
System.out.println(nsContext
.getNamespaceURI(XMLConstants.XML_NS_PREFIX));
完全放弃前缀可能会导致表达式不明确 - 如果要删除命名空间前缀,则需要更改文档格式。从文档创建上下文不一定有意义。前缀必须与 XPath 表达式中使用的前缀匹配,而不是与任何文档中的前缀匹配,如以下代码所示:
String xml = "<data xmlns=\"http://base\" xmlns:foo=\"http://foo\" >"
+ "<foo:value>"
+ "hello"
+ "</foo:value>"
+ "</data>";
String expression = "/stack:data/overflow:value";
class BaseFooContext implements NamespaceContext {
@Override
public String getNamespaceURI(String prefix) {
if ("stack".equals(prefix))
return "http://base";
if ("overflow".equals(prefix))
return "http://foo";
throw new IllegalArgumentException(prefix);
}
@Override
public String getPrefix(String namespaceURI) {
throw new UnsupportedOperationException();
}
@Override
public Iterator<String> getPrefixes(
String namespaceURI) {
throw new UnsupportedOperationException();
}
}
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
xpath.setNamespaceContext(new BaseFooContext());
String value = xpath.evaluate(expression,
new InputSource(new StringReader(xml)));
System.out.println(value);