将整数变量用于XPath表达式Java以从具有命名空间的重复节点中提取信息

时间:2011-10-24 04:12:44

标签: java xpath

解决!谢谢你们!

你的建议让我得到答案。所以你们都应该感谢你的建议。

放置int变量的解决方案如下:

//Put my xpath into a string variable where it can evaluate my integer "counter"

String myString = "/*[local-name()='root' and namespace-uri()='DK']/*[local-name()='book' and namespace-uri()='DK']" + counter + "]/*[local-name()='item1' and namespace-uri()='DK']/*[local-name()='item2' and namespace-uri()='DK']/*[local-name()='date' and namespace-uri()='DK'][" + counter + "]"


//Then simply put that string variable into the xpath expression.
System.out.print(myString); 

以下原始问题:

首先,我感谢任何帮助。提前感谢您的帮助。

我有一个需要解析的XML文件。

让我们举例说......

<root xmlns="DK">
  <book>
    <item1>
      <item2>
        <date>xxx
        </date>
        <date>x1x1x1
        </date>
      </item2>
    </item1>
  </book>
  <book>
    <item1>
      <item2>
        <date>yyy
        </date>
        <date>y1y1y1
        </date>
      </item2>
    </item1>
  </book>    
</root>

所以基本上,我正在寻找节点&lt;日期和GT;用xxx然后移动到同一节点&lt;日期和GT;在下一本包含yyy的书中。

输入的xml文件将包含未知数量的重复书籍,每本书都有不同的信息。

我选择尝试这样的事情。

// I've imported from dom4j SAXreader. I probably could use something different.
import org.dom4j.io.SAXReader;



// Variables
Document document = null;       

// Take input from file    
SAXReader reader = new SAXReader();
document = reader.read("E:/templates/test.xml");

int counter = 0;
int numofbooks = 0;

Element root = document.getRootElement();

for ( Iterator i = root.elementIterator("book"); i.hasNext();) {
    Element element = (Element) i.next();

counter = counter + 1;
numofbooks = counter;
}

System.out.println("There are " + numofbooks + " books required for processing");
while(counter != numofbooks); {
counter = counter + 1;

System.out.print("The values are: ");

// ----- This here is my problem code ----- //
System.out.print(/*[local-name()='root' and namespace-uri()='DK']/*[local-name()='book' and namespace-uri()='DK'][counter]/*[local-name()='item1' and namespace-uri()='DK']/*[local-name()='item2' and namespace-uri()='DK']/*[local-name()='date' and namespace-uri()='DK'][counter]).getStringValue());


System.out.print(" respectively");
}

我的问题在于此。因为有一些具有完全相同名称的重复节点是嵌套的,所以我使用整数计数器变量按数字抓取它们。

我的XPath表达式不明白我正在放入一个整数变量“counter”。

我可以使用任何语法来完成这项工作吗? 或者这是不可能的?

提前致谢。

DK

3 个答案:

答案 0 :(得分:1)

我没有在您的代码中看到对XPath API的任何调用,只是注释中的一个非常令人困惑的XPath表达式。

以下代码会在 NodeList中为您提供第一个 <date>的{​​{1}}:

<item2>

鉴于您的问题中的XML代码段,上面的代码将输出:

XPath xpath = XPathFactory.newInstance().newXPath();
NodeList dates = (NodeList) xpath.evaluate("/DK:root/DK:book/DK:item1/DK:item2/DK:date[1]", document, XPathConstants.NODESET);

for (int i = 0; i < dates.getLength(); i++) {
    Node item = dates.item(i);
    String content = item.getTextContent().trim();
    System.err.println(content);
}

请注意,XPath从1开始计数,因此xxx yyy 是第一个元素,而不是Java中的第二个元素。

如果您不需要名称空间感知,则可以只使用date[1](可能会删除对"/root/book/item1/item2/date[1]"或同等名称的调用)

如果DocumentBuilderFactory.setNamespaceAware(true);在整个文档中是唯一的,您甚至可以将XPath表达式减少到item2“(对于NS感知,如上所述,使用"//item2/date[1]为两个路径段添加前缀)。< / p>

答案 1 :(得分:1)

您可以在XPath表达式中引用变量$counter,并且可以通过定义XPathVariableResolver并将其与XPathFactory相关联来设置Java API中变量的值。

答案 2 :(得分:0)

即使存在事先未知的嵌套,也可以使用XPath表达式,如:

(//*[local-name()='root' and namespace-uri()='DK'])[$k]

其中$k可以用正整数代替。

请注意

  1. 上述表达式中的括号是必要的。

  2. XPath中的索引是基于1的,而不是基于C#或C ++的0。