【问题标题】:Unable to construct Document object from xml string无法从 xml 字符串构造 Document 对象
【发布时间】:2015-06-23 08:26:57
【问题描述】:

我的应用程序中有 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>

我想以此构造 Document 对象,以便使用 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/ 我没有看到任何错误。

知道我做错了什么吗?

【问题讨论】:

  • 什么是标题? header.concat(str) 的结果是什么?如果 XML 有效,为什么要在开头添加一些内容?
  • 另请注意,此 xml 是一个命名空间的,这意味着您可能还需要实现命名空间上下文。
  • JP Moresmau,抱歉,“标题”不存在。它的新 StringReader(str),其中 str 是我提到的 xml 字符串。亚瑟,我听不懂,你能详细说明一下吗?
  • 当您说“将文档对象设为空”时,您如何确定这一点?如果没有例外,那么 document 变量的值将不是是 Java null,而是非空 Document DOM 节点的 toString 表示形式(即您将从 @ 获得的内容) 987654327@) 是一个类似"[#document:null]"的字符串
  • 正确的伊恩。所以这意味着 Document 还没有形成对吗?如果我使用 xpath 访问地址,例如 xPath.evaluate("//loc:address/text()", document);我的地址为空

标签: java xml xpath xml-parsing


【解决方案1】:

正如 Arthur Elrich 在 cmets 中指出的那样,您应该让工厂名称空间感知并为 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-namefunction 摆脱不知道命名空间的问题:

xpath.evaluate("//*[local-name() = 'address']/text()", document);

但是,这种替代方法的健壮性要低得多,因为它会检索所有名为 address 的元素,而不管它们的实际命名空间如何。

【讨论】:

  • 谢谢四十,我通过其他方式让它工作了。但是,您的解决方案也有效。干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多