无法从xml字符串构造Document对象

时间:2015-06-23 08:26:57

标签: java xml xpath xml-parsing

我有xml字符串来到我的appliaction,如下所示

<?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/我没有看到任何错误。

知道我做错了什么吗?

1 个答案:

答案 0 :(得分:0)

正如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的所有元素,而不管它们的实际名称空间是什么。