解析包含Java中的命名空间的xpath似乎需要使用NamespaceContext
对象,将前缀映射到命名空间URL,反之亦然.但是,NamespaceContext
除了自己实现它之外,我找不到任何其他机制.这似乎违反直觉.
问题:是否有任何简单的方法NamespaceContext
从文档中获取,或者创建一个或者失败,完全放弃前缀并指定具有完全限定名称的xpath?
McD*_*ell 12
可以在不编写自己的类的情况下获取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));
Run Code Online (Sandbox Code Playgroud)
完全放弃前缀可能会导致表达式含糊不清 - 如果要删除名称空间前缀,则需要更改文档格式.从文档创建上下文不一定有意义.前缀必须与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);
Run Code Online (Sandbox Code Playgroud)
StAX API返回的实现和上面的实现都没有实现doc中定义的完整类/方法契约.您可以在此处获得完整的基于地图的实施.
我自己一直在使用xpath和NamespaceContexts.我在developerworks上遇到了一个很好的处理问题.
我在名为NamespaceContextImpl的" Apache WebServices Common Utilities "中找到了一个方便的实现.
您可以使用以下maven依赖项来获取此类:
<dependency>
<groupId>org.apache.ws.commons</groupId>
<artifactId>ws-commons-util</artifactId>
<version>1.0.1</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我以下面的方式使用它(我知道它是为sax构建的,但是在阅读完代码之后,它还可以):
NamespaceContextImpl nsContext = new NamespaceContextImpl();
nsContext.startPrefixMapping("foo", "my.name.space.com");
Run Code Online (Sandbox Code Playgroud)
您不需要调用endPrefixMapping.
归档时间: |
|
查看次数: |
18883 次 |
最近记录: |