使用XPATH表达式和Java解析XML文件 [英] Parse XML file using XPATH expressions and Java

查看:101
本文介绍了使用XPATH表达式和Java解析XML文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想解析一个xml文件,我正在使用Java和xpath评估。



我想使用xpath表达式输出当前的节点同级,没有
使用getNextSibling()函数,这是可能吗?



eg如果我们读取名称元素,我想添加xpath表达式=./地址
,以便输出name的同级,而不使用getNextSibling()/。



xml文件如下:

 < root> 
< name>
< address>
<职业>
< / root>

我的代码如下:

  package dom_stack4; 

import org.w3c.dom。*;
import javax.xml.xpath。*;
import javax.xml.parsers。*;
import java.io.IOException;
import org.xml.sax.SAXException;


public class Dom_stack4 {

public static void main(String [] args)throws ParserConfigurationException,SAXException,
IOException,XPathExpressionException {
// TODO代码应用逻辑这里


DocumentBuilderFactory domFactory =
DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
文档doc = builder.parse(root.xml);
XPath xpath = XPathFactory.newInstance()。newXPath();
//显示所有节点的XPath查询值
XPathExpression expr = xpath.compile(/ root / name / text());

对象结果= expr.evaluate(doc,XPathConstants.NODESET);
NodeList nodes =(NodeList)result; (int i = 0; i< nodes.getLength(); i ++){
System.out.println(Name is:+ nodes.item(i).getNodeValue()) ;

/ *这是可能吗? * /
/ * ./address/text()=>输出当前的节点sibling * /
expr = xpath.compile(./ address / text());
对象result1 = expr.evaluate(doc,XPathConstants.NODESET);
NodeList nodes1 =(NodeList)result1;
for(int j = 0; j< nodes1.getLength(); j ++){
System.out.println(---------------- + nodes1.item(j).getNodeValue());
}

}
}
}



谢谢,提前

解决方案

首先,如果您使用正确形式的xml运行代码,应该关闭名称地址和职业标签,否则当您尝试解析时会收到错误。其次,如果要选择该节点的文本子节点,则需要确保其中有某些内容,因此您的xml应该如下所示:

 <根> 
< name> hi< / name>
< address> hi< / address>
< profession> hi< / profession>
< / root>

现在,您为选择名称元素的文本是好的,所以从您的 IS可能在这里?评论有一些你需要做的更改。



如果你想评估一个亲戚XPath,您不想将文档对象传递给XPath的评估方法。正在评估XPath的当前位置由您提供给它的项目决定,并且文档对象总是在根目录下进行计算。如果您想要相对于特定节点进行评估,而不是将其提供给该文档,请给它该节点。



因此,您的评估方法调用:

  Object result1 = expr.evaluate(nodes.item(i),XPathConstants.NODESET); 

接下来,你应该确保你的XPath实际上是正确的。我们当前选择的节点是名称的文本节点。这意味着我们需要先去名称节点而不是文本节点。 XPath语法中的表达式选择当前节点,所以您正在做的是选择相同的节点。您想要选择父节点的 .. 表达式。



所以使用我们当前的XPath .. 我们选择名称节点。我们想要做的是选择名称节点的同义的地址节点。有两种方法可以做到这一点,我们可以选择名称节点的父节点,根节点和选择该节点的子节点,或者我们可以使用XPath轴来选择兄弟节点(关于轴的信息可以是在这里找到 http://www.w3schools.com/xpath/xpath_axes.asp



如果我们要遍历根节点,我们需要选择我们当前节点的父节点的父节点,以便 ../ .. 这给我们的根节点,后跟地址child: ../../ address / text(),这将给我们所有的地址兄弟姐妹。



或者,使用轴,我们可以执行 .. 选择名称节点,后跟 ../ following-sibling :: address (注意:只有在名称节点后面的地址节点是后才可以),然后选择文本具有 ../ following-sibling的地址节点:address / text()



这给我们这两条线作为

  expr = xpath.compile(../../地址/文本()); 
对象result1 = expr.evaluate(nodes.item(i),XPathConstants.NODESET);

  expr = xpath.compile(../ following-sibling :: address / text()); 
对象result1 = expr.evaluate(nodes.item(i),XPathConstants.NODESET);


I would like to parse an xml file and i'm using Java and xpath evaluation.

I would like to output the current's node sibling with an xpath expression and without using getNextSibling() function, is that possible?

e.g. if we read the name element i would like to add the xpath expression ="./address" in order to output the sibling of "name" without using getNextSibling()/.

The xml file is as follows:

  <root>            
        <name>
        <address>
        <profession>
  </root>

My code is as follows:

  package dom_stack4;

  import org.w3c.dom.*;
  import javax.xml.xpath.*;
  import javax.xml.parsers.*;
  import java.io.IOException;
  import org.xml.sax.SAXException;


  public class Dom_stack4 {

public static void main(String[] args) throws ParserConfigurationException,       SAXException, 
    IOException, XPathExpressionException {
    // TODO code application logic here


    DocumentBuilderFactory domFactory = 
    DocumentBuilderFactory.newInstance();
    domFactory.setNamespaceAware(true); 
    DocumentBuilder builder = domFactory.newDocumentBuilder();
    Document doc = builder.parse("root.xml");
    XPath xpath = XPathFactory.newInstance().newXPath();
     // XPath Query for showing all nodes value
    XPathExpression expr = xpath.compile("/root/name/text()");

    Object result = expr.evaluate(doc, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++) {
          System.out.println(" Name is : " +  nodes.item(i).getNodeValue()); 

          /* IS that possible here ?? */
         /* ./address/text() => outputs the current's node sibling */
          expr = xpath.compile("./address/text()");
          Object result1 = expr.evaluate(doc, XPathConstants.NODESET);
          NodeList nodes1 = (NodeList) result1;
           for (int j = 0; j < nodes1.getLength(); j++) {
               System.out.println(" ---------------- " + nodes1.item(j).getNodeValue()); 
              }

    }
    }
    }

Thanks, in advance

解决方案

First off, it would be good if you were running your code using properly formed xml, the name address and profession tags should be closed or you will get an error when you try to parse it. Secondly, if you want to select the text child of the node, you need to make sure there is actually something there, so your xml should look something like this:

<root>
    <name>hi</name>
    <address>hi</address>
    <profession>hi</profession>
</root>

Now, what you have for selecting the text of the name element is fine, so starting with your IS that possible here ?? comment there are some changes you need to make.

If you want to evaluate a relative XPath, you don't want to be passing your document object to the XPath's evaluate method. The current location that the XPath is being evaluated from is determined by the item that you give to it, and the document object is always evaluated at the root. If you want to evaluate relative to a specific node, rather than giving it the document, give it that node.

So you would have something like this for your evaluate method call:

Object result1 = expr.evaluate(nodes.item(i), XPathConstants.NODESET);

Next, you should make sure that your XPath is actually correct. The node that we currently have selected is the text node of name. Which means we need to first go to the name node instead of the text node. The . expression in XPath syntax selects the current node, so all you are doing with that is selecting the same node. You want the .. expression which selects the parent node.

So with our current XPath of .. we are selecting the name node. What we want to do is select address nodes that are sibilings of the name node. There are two ways we can do this, we could select the parent of the name node, the root node, and select address nodes that are children of that, or we could use an XPath axis to select the siblings (information about axes can be found here http://www.w3schools.com/xpath/xpath_axes.asp)

If we are going through the root node, we would need to select the parent of the parent of our current node so ../.. which gives us the root node, followed by the address children: ../../address/text(), which would give us all address siblings.

Alternatively, using an axis, we could do .. to select the name node followed by ../following-sibling::address (NOTE: this only works if the address nodes are after the name node) and then select the text of the address nodes with ../following-sibling:address/text().

This gives us those two lines as either

expr = xpath.compile("../../address/text()"); 
Object result1 = expr.evaluate(nodes.item(i), XPathConstants.NODESET);

or

expr = xpath.compile("../following-sibling::address/text()");
Object result1 = expr.evaluate(nodes.item(i), XPathConstants.NODESET);

这篇关于使用XPATH表达式和Java解析XML文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆