在 XPath 表达式中使用整数变量 Java 从具有名称空间的重复节点中提取信息

发布于 2024-12-11 07:00:41 字数 2544 浏览 1 评论 0原文

解决了!谢谢你们!

你的建议让我找到了答案。所以你们所有人的建议都值得感谢。

放置 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>

所以基本上,我正在寻找节点 <日期>与 xxx 然后移动到同一个节点 <日期>在包含 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 表达式不明白我放入了一个整数变量“计数器”。

我可以使用任何语法来完成这项工作吗? 还是根本不可能?

提前致谢。

德克

Solved! Thank you guys!

Your suggestions led me to the answer. So all of you deserve thanks for the suggestion.

The solution to putting a int variable is the following:

//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); 

Original Question below:

Firstly, I appreciate any help. Thanks in advance for any help.

I have an XML file that I need to parse.

Lets say for example...

<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>

So basically, I'm looking for the node < date> with xxx and then move on to the same node < date> in the next book which contains yyy.

The input xml file will have an unknown amount of repeating books with different information for each book.

I've chosen to try something like this.

// 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");
}

My problem lies here. Because there are a few repeated nodes with the exact same name that are nested, I'm grabbing them out by number using an integer counter variable.

My XPath expression doesn't understand that I'm putting in a variable "counter" that is an integer.

Is there any syntax I can use to make this work?
Or is it just not possible?

Thanks in advance.

DK

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浪推晚风 2024-12-18 07:00:41

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

You can refer to a variable $counter in your XPath expression, and you can set the value of the variable from the Java API by defining an XPathVariableResolver and associating it with your XPathFactory.

§对你不离不弃 2024-12-18 07:00:41

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

以下代码为您获取 each first NodeList ;

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);
}

给定问题中的 XML 片段,上面的代码将输出:

xxx
yyy

请注意,XPath 从 1 开始计数,因此 date[1] 是第一个元素,而不是第二个元素将在Java中。

如果您不需要命名空间感知,则可以仅使用 "/root/book/item1/item2/date[1]" (并且可能删除对 DocumentBuilderFactory.setNamespaceAware(true ); 或等效项)

如果 item2 在整个文档中是唯一的,您甚至可以将 XPath 表达式简化为 "//item2/date[1]" (为了NS 意识,在两个路径段前面加上 DK: ,如上所述)。

I don't see any calls to the XPath API in your code, just a very confusing XPath expression in a comment.

The following code gets you a NodeList of the first <date> in each <item2>:

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);
}

Given the XML snippet in your question, the above code will output:

xxx
yyy

Note that XPath starts counting from 1, so date[1] is the first element, not the second as it would be in Java.

If you don't need namespace awareness, you can use just "/root/book/item1/item2/date[1]" (and probably remove a call to DocumentBuilderFactory.setNamespaceAware(true); or equivalent)

If item2 is unique in the whole document, you can even reduce the XPath expression to "//item2/date[1]" (for NS awareness, prefix both path segments with DK: as above).

半城柳色半声笛 2024-12-18 07:00:41

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

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

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

请注意

  1. 上面表达式中的括号是必需的。

  2. XPath 中的索引是从 1 开始的,而不是像 C# 或 C++ 中那样从 0 开始。

Even if there is nestedness that isn't known in advance, one can use an XPath expression like:

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

where $k can be substituted with a positive integer.

Do note:

  1. The brackets in the above expression are necessary.

  2. Indexing in XPath is 1 - based, not 0 -based as in C# or C++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文