xpath获取特定的previous-sibling的最后一个

时间:2022-11-26 23:49:15

Here's something really simple (at least I guess), I just do not get the clue.

这是非常简单的事情(至少我猜),我只是没有得到线索。

I have to parse a large XML document to get a specific node, identified by one of its subnode values. Thats easy so far. But when I try to parse onward from that node relatively upward, selecting the preceding-siblings of its ancestor by using a predicate I get a list of nodes, from that on I have to walk downward again.

我必须解析一个大型XML文档以获取一个特定节点,该节点由其子节点值之一标识。到目前为止这很容易。但是当我尝试从该节点向前解析时,通过使用谓词选择其祖先的前兄弟,我得到一个节点列表,从那里我必须再次向下走。

In Theorie, that is a table, with 5 columns and two rows (in the shown example below). I get just the id element of one field, and need to find the name given in the first field of the row. The first field is always of type 'Link' and has a name subnode with text - which is the thing to get.

在Theorie中,这是一个表,有5列和2行(在下面的例子中)。我得到一个字段的id元素,需要找到行的第一个字段中给出的名称。第一个字段始终为“链接”类型,并且具有带文本的名称子节点 - 这是要获取的内容。

In other words, I need to move from any node with an <id>XXX_X</i> to the next preceding-sibling cell with a control of xsi:type='Label' and a name node. From the node <id>MyItemId_1</> I need to get the second preceding-sibling, from the node <id>MyItemId_4</id> I need to get the 5th preceding-sibling.

换句话说,我需要从具有 XXX_X 的任何节点移动到具有xsi:type ='Label'和名称节点的控件的下一个在前兄弟单元格。从节点 MyItemId_1 我需要获得第二个前一个兄弟,从节点 MyItemId_4 我需要获得第5个前面的兄弟。

This is a sample xml piece:

这是一个示例xml片段:

<cell>
    <control xsi:type="Label">
        <id>1234</id>
        <name>MyOtherItemName</name>
        <message/>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Label">
        <id>MyOtherItemId_0</id>
        <name/>
        <message/>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Label">
        <id>MyOtherItemId_1</id>
        <name/>
        <message/>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Button">
        <id>MyOtherItemId_2</id>
        <name>552</name>
        <message/>
        <type>Link</type>
        <selected>false</selected>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Button">
        <id>MyOtherItemId_3</id>
        <name>432</name>
        <message/>
        <type>Link</type>
        <selected>false</selected>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Button">
        <id>MyOtherItemId_4</id>
        <name>33</name>
        <message/>
        <type>Link</type>
        <selected>false</selected>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Label">
        <id>1234</id>
        <name>MyItemName</name>
        <message/>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Label">
        <id>MyItemId_0</id>
        <name/>
        <message/>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Label">
        <id>MyItemId_1</id>
        <name/>
        <message/>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Button">
        <id>MyItemId_2</id>
        <name>552</name>
        <message/>
        <type>Link</type>
        <selected>false</selected>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Button">
        <id>MyItemId_3</id>
        <name>432</name>
        <message/>
        <type>Link</type>
        <selected>false</selected>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>
<cell>
    <control xsi:type="Button">
        <id>MyItemId_4</id>
        <name>33</name>
        <message/>
        <type>Link</type>
        <selected>false</selected>
    </control>
    <selected>false</selected>
    <style>Odd</style>
</cell>

I do get the item i have to get with this xpath:

我得到了这个xpath必须得到的项目:

//cell[control[type='Link']]/control[type='Link' and selected='false' and id='MyItemId_3']/id

That selects the id of the control of the cell, namely the 4th column in the second row, of the rendered table.

它选择渲染表的单元格控件的id,即第二行的第4列。

From that node on I try moving to the first cell in the row by following this path:

从该节点开始,我尝试按照以下路径移动到该行中的第一个单元格:

../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]]/control[name[node()]]/name

That gives me the two correct cells of the first column of the table.

这给了我表格第一列的两个正确单元格。

<name>MyOtherItemName</name>
* * * * * * * * * *
<name>MyItemName</name>

Now it breaks my back since I can't get it to just give me back the last one of the two selected.

现在它打破了我的背部,因为我无法让它回到所选择的两个中的最后一个。

I tried this:

我试过这个:

../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]][1]/control[name[node()]]/name

which is a preceding-sibling selection with a predicate to exactly the sort of siblings I search for, but it seems I can not combine that predicate with a [1] selector. Instead of selecting the desired first preceding sibling "MyItemName" it selects the first sibling from all preceding ones "MyOtherItemName".

这是一个先前兄弟选择,其谓词正是我搜索的兄弟姐妹的类型,但似乎我无法将该谓词与[1]选择器结合起来。它不是选择所需的第一个前一个兄弟“MyItemName”,而是从前面的所有兄弟“MyOtherItemName”中选择第一个兄弟。

I need help, hope someone here has a clue and can pinpoint me in the right direction.

我需要帮助,希望这里有人有一个线索,可以指出我正确的方向。

Exactly what I set up to get this work is copying the xml into http://www.bit-101.com/xpath/ and working with the concatenated xpathes on it to simulate what the software should do:

我为实现这项工作而设置的正是将xml复制到http://www.bit-101.com/xpath/并使用连接的xpathes来模拟软件应该做的事情:

//cell[control[type='Link']]/control[type='Link' and selected='false' and id='MyItemId_3']/id/../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]]/control[name[node()]]/name

3 个解决方案

#1


12  

I do not understand what the problem exactly is, but preceding-siblings are sorted from the node itself towards the beginning of the document, i.e. the other way round than in the document. To get the nearest preceding sibling, use preceding-sibling[1], to get the farthest one (i.e. the first one in the document order), use preceding-sibling[last()].

我不明白究竟是什么问题,但是兄弟姐妹从节点本身向文档的开头排序,即反过来比在文档中排序。要获得最近的前一个兄弟,请使用previous-sibling [1],以获得最远的兄弟(即文档顺序中的第一个),使用previous-sibling [last()]。

#2


1  

After reading your update, wouldn't this work:

阅读完更新后,这不会起作用:

//cell[control/id="MyItemId_4"]/preceding-sibling::cell[control[@xsi:type='Label']  and not(control/name='')][1]

I'm a bit unsure about the name node: do you want to test for existence of text in the the name node or just existence of the name node itself?

我对名称节点有点不确定:您是要测试名称节点中是否存在文本,还是仅存在名称节点本身?

#3


1  

YourWebElement.FindElement(By.XPath("preceding-sibling::*[1]"));

YourWebElement.FindElement(By.XPath( “前同辈:: * [1]”));

Here 1 indicates just the sibling above the selected node and then you can do recursion in order to get all the preceding siblings from bottom to top.

这里1表示所选节点上方的兄弟节点,然后您可以进行递归,以便从下到上获取所有前面的兄弟节点。

#1


12  

I do not understand what the problem exactly is, but preceding-siblings are sorted from the node itself towards the beginning of the document, i.e. the other way round than in the document. To get the nearest preceding sibling, use preceding-sibling[1], to get the farthest one (i.e. the first one in the document order), use preceding-sibling[last()].

我不明白究竟是什么问题,但是兄弟姐妹从节点本身向文档的开头排序,即反过来比在文档中排序。要获得最近的前一个兄弟,请使用previous-sibling [1],以获得最远的兄弟(即文档顺序中的第一个),使用previous-sibling [last()]。

#2


1  

After reading your update, wouldn't this work:

阅读完更新后,这不会起作用:

//cell[control/id="MyItemId_4"]/preceding-sibling::cell[control[@xsi:type='Label']  and not(control/name='')][1]

I'm a bit unsure about the name node: do you want to test for existence of text in the the name node or just existence of the name node itself?

我对名称节点有点不确定:您是要测试名称节点中是否存在文本,还是仅存在名称节点本身?

#3


1  

YourWebElement.FindElement(By.XPath("preceding-sibling::*[1]"));

YourWebElement.FindElement(By.XPath( “前同辈:: * [1]”));

Here 1 indicates just the sibling above the selected node and then you can do recursion in order to get all the preceding siblings from bottom to top.

这里1表示所选节点上方的兄弟节点,然后您可以进行递归,以便从下到上获取所有前面的兄弟节点。