无法使用已编译的XPATH表达式解析XML文件?

时间:2012-05-28 00:16:13

标签: java xml xpath xml-parsing

我正在处理a tutorial并遇到了一个我预期可以解决的问题。我希望有人可以帮我这个代码。我无法超越这个。如果我使用XPATH表达式“ // * / text()”,我在下面分享的代码将匹配,但是当我得到更具体的内容并且使用“ // tag0时,它无法匹配:G / text()“。知道我做错了什么吗?我只是想从下面提供的XML中获取2“tag0:G”值:

import java.io.IOException;
import java.io.StringReader;    
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;    
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;    
public class Test1 {        
  public static void main(String[] args) {
    System.out.println("Test start...");
    String myXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
    "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
    "<soapenv:Body>" +
    "<tag0:getA xmlns:tag0=\"http://me.ws.ix\">" +
    "<tag0:B>" +
    "<tag0:CC>" +
    "<tag0:CC>" +
    "<tag0:D>false</tag0:D>" +
    "<tag0:E>false</tag0:E>" +
    "<tag0:F xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\"/>" +
    "<tag0:G>10001</tag0:G>" +
    "<tag0:H>7744000002</tag0:H>" +
    "</tag0:CC>" +
    "<tag0:CC>" +
    "<tag0:D>false</tag0:D>" +
    "<tag0:E>false</tag0:E>" +
    "<tag0:F xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\"/>" +
    "<tag0:G>20002</tag0:G>" +
    "<tag0:H>1111122222</tag0:H>" +
    "</tag0:CC>" +
    "</tag0:CC>" +
    "<tag0:I>2012-05-27 23:38:48</tag0:I>" +
    "</tag0:B>" +
    "</tag0:getA>" +
    "</soapenv:Body>" +
    "</soapenv:Envelope>";

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    Document doc = null;
    NodeList nodes = null;
    try {           
      doc = factory.newDocumentBuilder().parse( new InputSource( new StringReader( myXML) ) );
      XPathExpression expr = XPathFactory.newInstance().newXPath()
        .compile("//tag0:G/text()"); // this fails, I don't know why
      nodes = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);
    } catch (SAXException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    } catch (XPathExpressionException e) {
      e.printStackTrace();
    }
    System.out.println("Nodes length: " + nodes.getLength() );
    for (int i = 0; i < nodes.getLength(); i++) { 
      String val = nodes.item(i).getNodeValue(); 
      System.out.println( "Val: " + val ); 
    }
    System.out.println("Test end...");
  }    
}

2 个答案:

答案 0 :(得分:2)

在开始编译XPath表达式之前,您应该在XPath实例上注册 NamespaceContext 。您可以使用XPath#setNamespaceContext(NamespaceContex nsContext)

请在xml.apache.org上阅读using NamespaceContext chapter

我们的想法是,在使用命名空间信息解析文档时,XPath执行程序需要知道如何将您使用的前缀与运行它的文档中的命名空间URI进行匹配。前缀本身没有任何内容,只要映射到相同的URI,您就可以使用任意前缀。

P.S。这里有更多矿石Namespaces in XML

答案 1 :(得分:0)

当然你也可以作弊 - 如果每次出现的“G”(或你所追求的任何元素)来自同一名称空间 - 你可以简单地做到

//*[local-name()='G'] 

然而,虽然这是有效的,但这只是绕过了这个问题。你可能只是咬紧牙关并跨越命名空间......