Java中带有命名空间的XPath
Posted
技术标签:
【中文标题】Java中带有命名空间的XPath【英文标题】:XPath with namespace in Java 【发布时间】:2012-11-22 01:30:57 【问题描述】:我想获取标签之间的所有内容,但由于 urn: 命名空间,我不知道该怎么做。
<urn:ResponseStatus version="1.0" xmlns:urn="urn:camera-org">
<urn:requestURL>/CAMERA/Streaming/status</urn:requestURL>
<urn:statusCode>4</urn:statusCode>
<urn:statusString>Invalid Operation</urn:statusString>
<urn:id>0</urn:id>
</urn:ResponseStatus>
有什么想法吗?
【问题讨论】:
你用的是什么库?您是否尝试在查询前加上urn:
?
使用 javax.xml.xpath.XPath;我试过 urn: 但这没有帮助。
【参考方案1】:
-
简答:使用 XPath
local-name()
。像这样:xPathFactory.newXPath().compile("//*[local-name()='requestURL']/text()");
将返回 /CAMERA/Streaming/status
或者您可以实现一个 NamespaceContext
,它映射命名空间名称和 URI,并在查询之前将其设置在 XPath 对象上。
看看这个blog article,更新:文章下架了,大家可以在webarchive看到
解决方案 1 示例:
XPath xpath = XPathFactory.newInstance().newXPath();
String responseStatus = xpath.evaluate("//*[local-name()='ResponseStatus']/text()", document);
System.out.println("-> " + responseStatus);
解决方案 2 示例:
// load the Document
Document document = ...;
NamespaceContext ctx = new NamespaceContext()
public String getNamespaceURI(String prefix)
return prefix.equals("urn") ? "urn:camera-org" : null;
public Iterator getPrefixes(String val)
return null;
public String getPrefix(String uri)
return null;
;
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(ctx);
String responseStatus = xpath.evaluate("//urn:ResponseStatus/text()", document);
System.out.println("-> " + responseStatus);
编辑
这是一个完整的例子,它正确地检索了元素:
String xml = "<urn:ResponseStatus version=\"1.0\" xmlns:urn=\"urn:camera-org\">\r\n" + //
"\r\n" + //
"<urn:requestURL>/CAMERA/Streaming/status</urn:requestURL>\r\n" + //
"<urn:statusCode>4</urn:statusCode>\r\n" + //
"<urn:statusString>Invalid Operation</urn:statusString>\r\n" + //
"<urn:id>0</urn:id>\r\n" + //
"\r\n" + //
"</urn:ResponseStatus>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new java.io.ByteArrayInputStream(xml.getBytes()));
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext()
public String getNamespaceURI(String prefix)
return prefix.equals("urn") ? "urn:camera-org" : null;
public Iterator<?> getPrefixes(String val)
return null;
public String getPrefix(String uri)
return null;
);
XPathExpression expr = xpath.compile("//urn:ResponseStatus");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++)
Node currentItem = nodes.item(i);
System.out.println("found node -> " + currentItem.getLocalName() + " (namespace: " + currentItem.getNamespaceURI() + ")");
【讨论】:
好答案! (如果代码被缩进并且示例 XML 没有被他自己的服务器吃掉,那篇博文会更有用。哦,好吧,最后仍然是一个有用的列表。) 非常感谢!我使用这个逻辑解析了一个巨大的复杂 xml 文件,它对我有用。getNamespaceURI
应该返回 XMLConstants.NULL_NS_URI
(这是一个空字符串)而不是 null 当它不匹配任何注册的前缀。
blog.davber.com 网站现在只返回内部服务器错误。
全部:我通过 webarchive 更新了第 3 点中原始博客文章的链接的答案【参考方案2】:
XML xpath 与 Namespace
简单的 XML
String namespaceXML = "<?xml version='1.0' ?><information><person id='1'><name>Deep</name><age>34</age><gender>Male</gender></person> <person id='2'><name>Kumar</name><age>24</age><gender>Male</gender></person> <person id='3'><name>Deepali</name><age>19</age><gender>Female</gender></person><!-- more persons... --></information>";
String jsonString = "";
String expression = "//information";
名称空间 XML
String namespaceXML = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><m:NumberToDollarsResponse xmlns:m=\"http://www.dataaccess.com/webservicesserver/\"><m:NumberToDollarsResult>nine hundred and ninety nine dollars</m:NumberToDollarsResult></m:NumberToDollarsResponse></soap:Body></soap:Envelope>";
String jsonString = "'soap':'http://schemas.xmlsoap.org/soap/envelope/', 'm':'http://www.dataaccess.com/webservicesserver/'";
String expression = "//m:NumberToDollarsResponse/m:NumberToDollarsResult/text()";
将命名空间 xml 文件作为字符串提供给asscerionXpath(namespaceXML, jsonString, expression)
方法并以文本/节点的形式获取结果。
文本():
nine hundred and ninety nine dollars
节点:
<m:NumberToDollarsResult xmlns:m="http://www.dataaccess.com/webservicesserver/"> nine hundred and ninety nine dollars </m:NumberToDollarsResult>
public static String asscerionXpath(String namespaceXML, String jsonString, String expression)
if(namespaceXML.indexOf("><") > -1) namespaceXML = namespaceXML.replace("><", ">\r\n<");
if(jsonString.indexOf("'") > -1) jsonString = jsonString.replace("'", "\"");
System.out.println("namespaceXML : \n"+namespaceXML);
System.out.println("nsmespaces : \n"+jsonString);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(true);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
try
DocumentBuilder builder = factory.newDocumentBuilder();
Document source = builder.parse( string2Source(namespaceXML) );
XPath xpath = XPathFactory.newInstance().newXPath();
addNameSpaces(jsonString, xpath);
// An XPath expression is not thread-safe. Make sure it is accessible by only one Thread.
XPathExpression expr = xpath.compile(expression);
// The NodeList interface provides the abstraction of an ordered collection of nodes,
NodeList nodes = (org.w3c.dom.NodeList) expr.evaluate(source, XPathConstants.NODESET);;
Node tree_base = nodes.item(0);
return document2String(tree_base);
catch (UnsupportedEncodingException e)
e.printStackTrace();
catch (SAXException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (ParserConfigurationException e)
e.printStackTrace();
catch (XPathExpressionException e)
System.out.println("If the expression cannot be evaluated.");
return "";
static InputSource string2Source( String str )
InputSource inputSource = new InputSource( new StringReader( str ) );
return inputSource;
static void addNameSpaces(String jsonString, XPath xpath)
JSONParser parser = new JSONParser();
try
JSONObject namespaces = (JSONObject) parser.parse(jsonString);
if (namespaces.size() > 0)
final JSONObject declaredPrefix = namespaces; // To access in Inner-class.
NamespaceContext nameSpace = new NamespaceContext()
// To get all prefixes bound to a Namespace URI in the current scope, XPath 1.0 specification
// --> "no prefix means no namespace"
public String getNamespaceURI(String prefix)
Iterator<?> key = declaredPrefix.keySet().iterator();
System.out.println("Keys : "+key.toString());
while (key.hasNext())
String name = key.next().toString();
if (prefix.equals(name))
System.out.println(declaredPrefix.get(name));
return declaredPrefix.get(name).toString();
return "";
public Iterator<?> getPrefixes(String val)
return null;
public String getPrefix(String uri)
return null;
;// Inner class.
xpath.setNamespaceContext( nameSpace );
catch ( org.json.simple.parser.ParseException e)
e.printStackTrace();
【讨论】:
以上是关于Java中带有命名空间的XPath的主要内容,如果未能解决你的问题,请参考以下文章