xpath中的多个follow-sibling或previous-sibling

时间:2017-07-13 14:23:47

标签: xml xpath

流行测验!我有一个包含多行且没有唯一标识符的表。识别唯一行的唯一方法是匹配超过两个值(1 following-sibling和1 preceding-sibling无法工作)。以下是样本

<tr>
    <td>Map</td>
    <td>First</td>
    <td>Second</td>
    <td>Third</td>
    <td>A01</td>
    <td><a href='test0'>Test 0</a></td>
</tr>
<tr>
    <td>Map</td>
    <td>First</td>
    <td>Tenth</td>
    <td>Third</td>
    <td>A03</td>
    <td><a href='test1'>Test 1</a></td>
</tr>
<tr>
    <td>Map</td>
    <td>Second</td>
    <td>Fifth</td>
    <td>Forth</td>
    <td>A02</td>
    <td><a href='test2'>Test 2</a></td>
</tr>

我需要Test 2并且我有以下数据。

td[1]Map

td[2]Second

td[3]Fifth

td[4]Forth

td[5]A02

这是我尝试过的XPath:

//td/a[contains(., 'Test 2')][preceding-sibling::td[1][contains(., 'Map')] and td[2][contains(., 'Second')] and td[3][contains(., 'Fifth')] and td[4][contains(., 'Forth')] and td[5][contains(., 'A02')]]

我为此寻找解决方案而生气!非常感谢帮助!

2 个答案:

答案 0 :(得分:2)

如果将谓词放在tr ...

上可能会更容易
//tr[td[1]='Map' and td[2]='Second' and td[3]='Fifth' and td[4]='Forth' and td[5]='A02']/td[6]/a

//tr[td[1]='Map'][td[2]='Second'][td[3]='Fifth'][td[4]='Forth'][td[5]='A02']/td[6]/a

原始尝试不起作用的原因是因为上下文为aa根本没有任何前置兄弟。您需要执行../preceding-sibling::td ...

//a[../preceding-sibling::td[5]='Map' and ../preceding-sibling::td[4]='Second' and ../preceding-sibling::td[3]='Fifth' and ../preceding-sibling::td[2]='Forth' and ../preceding-sibling::td[1]='A02']

另请注意,使用前兄弟时,这些位置是向后的。

答案 1 :(得分:1)

获取包含一些子元素的元素:

tag[./child]

获取具有某个属性的子元素,该属性符合以下条件:[@id='someId'][contains(text(),'some text')]

tag[./child[condition]]

通过几个条件获取元素:

tag[condition1][condition2]

让我们将其收集到1个定位器中。所以要获得包含带文本的子元素的元素:

//tr[./td[text()='Map']]

所以要重复的模式是:[./td[text()='text']]

让我们添加一些其他必需的孩子:

//tr[./td[text()='Map']][./td[text()='Second']][./td[text()='Fifth']]

你可以轻松地创建一个java方法,这样可以将内部文本作为params并构建完整路径:

 public static String getPath(String... innerText) {
        StringBuilder path = new StringBuilder("//tr"); //before tr  - table could be specified
        Arrays.stream(innerText).forEach(
                text -> path.append("[./td[text()='").append(text).append("']]")
        );
        return path.toString();
    }

所以这里我们得到包含所需内部文本的tr。现在我们可以在其中搜索a标记。只需添加到定位器的末尾://a 或者如果您需要文字://a/text()

结果是:

//tr[./td[text()='Map']][./td[text()='Second']][./td[text()='Fifth']]//a