无法从 xml 字符串构造文档对象
Unable to construct Document object from xml string
我有 xml 字符串进入我的应用程序,如下所示
<?xml version="1.0" encoding="UTF-8"?><loc:getLocation xmlns:loc="http://www.csapi.org/schema/parlayx/terminal_location/v2_3/local">
<loc:address>tel:+919420161525</loc:address>
<loc:requestedAccuracy>500</loc:requestedAccuracy>
<loc:acceptableAccuracy>500</loc:acceptableAccuracy>
</loc:getLocation>
我想由此构建文档对象,以便使用 XPath 检索所需数据。我尝试了以下代码
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
Document document;
try
{
builder = factory.newDocumentBuilder();
document = builder.parse( new InputSource( new StringReader( header.concat(str) ) ) );
} catch (Exception e) {
e.printStackTrace();
}
但是我得到的 Document 对象为 null。我没有得到任何例外。我尝试在线验证我的 XML http://www.xmlvalidation.com/ 我没有看到任何错误。
知道我做错了什么吗?
正如 Arthur Elrich 在评论中指出的那样,您应该让工厂名称空间感知并为 XPath 实例提供名称空间上下文。
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse( new InputSource(new StringReader(...)));
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new MyNamespaceContext());
String s = xpath.evaluate("//location:address/text()", document);
System.out.println(s2);
以及一个简单的 NamespaceContext
实现:
static class MyNamespaceContext implements NamespaceContext {
@Override
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "location":
return "http://www.csapi.org/schema/parlayx/terminal_location/v2_3/local";
}
return null;
}
@Override
public String getPrefix(String namespaceURI) {
return null;
}
@Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
}
请注意,XPath 表达式中使用的前缀与文档中使用的前缀不同。它们当然可以相同,但是这个例子表明重要的是命名空间 URI,而不是前缀。
作为替代方案,您可以通过使用 local-name
函数来避免命名空间感知:
xpath.evaluate("//*[local-name() = 'address']/text()", document);
但是,此替代方法的健壮性要差得多,因为它会检索所有名为 address
的元素,而不管它们的实际名称空间如何。
我有 xml 字符串进入我的应用程序,如下所示
<?xml version="1.0" encoding="UTF-8"?><loc:getLocation xmlns:loc="http://www.csapi.org/schema/parlayx/terminal_location/v2_3/local">
<loc:address>tel:+919420161525</loc:address>
<loc:requestedAccuracy>500</loc:requestedAccuracy>
<loc:acceptableAccuracy>500</loc:acceptableAccuracy>
</loc:getLocation>
我想由此构建文档对象,以便使用 XPath 检索所需数据。我尝试了以下代码
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
Document document;
try
{
builder = factory.newDocumentBuilder();
document = builder.parse( new InputSource( new StringReader( header.concat(str) ) ) );
} catch (Exception e) {
e.printStackTrace();
}
但是我得到的 Document 对象为 null。我没有得到任何例外。我尝试在线验证我的 XML http://www.xmlvalidation.com/ 我没有看到任何错误。
知道我做错了什么吗?
正如 Arthur Elrich 在评论中指出的那样,您应该让工厂名称空间感知并为 XPath 实例提供名称空间上下文。
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse( new InputSource(new StringReader(...)));
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new MyNamespaceContext());
String s = xpath.evaluate("//location:address/text()", document);
System.out.println(s2);
以及一个简单的 NamespaceContext
实现:
static class MyNamespaceContext implements NamespaceContext {
@Override
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "location":
return "http://www.csapi.org/schema/parlayx/terminal_location/v2_3/local";
}
return null;
}
@Override
public String getPrefix(String namespaceURI) {
return null;
}
@Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
}
请注意,XPath 表达式中使用的前缀与文档中使用的前缀不同。它们当然可以相同,但是这个例子表明重要的是命名空间 URI,而不是前缀。
作为替代方案,您可以通过使用 local-name
函数来避免命名空间感知:
xpath.evaluate("//*[local-name() = 'address']/text()", document);
但是,此替代方法的健壮性要差得多,因为它会检索所有名为 address
的元素,而不管它们的实际名称空间如何。