我有一个XML如下:

<object>
    <codes>
        <cd1>A</cd1>
        <cd2>B</cd2>
        <cd3>C</cd3>
    </codes>
    <codes>
        <cd1>A</cd1>
        <cd2>D</cd2>
        <cd3></cd3>
    </codes>
    <codes>
        <cd1>E</cd1>
        <cd2>D</cd2>
        <cd3></cd3>
    </codes>
</object>


到目前为止,我的XPath演变如下:


//cd1|//cd2|//cd3:获取所有cd1,cd2和cd3元素
(//cd1|//cd2|//cd3)[text()[1]]:从上面的列表中过滤所有具有非空文本值的元素,并返回下面的元素。

<cd1>A</cd1><cd2>B</cd2><cd3>C</cd3><cd1>A</cd1><cd2>D</cd2><cd1>E</cd1><cd2>D</cd2>
现在,我需要删除具有重复文本值的元素。我已经尝试将xpath作为(//cd1|//cd2|//cd3)[text()[1]][(preceding::cd1)|(preceding::cd2)|(preceding::cd3)]。我是什么
希望实现的是检查该值是否在上述cd1或cd2或cd3中的任何一个之前。但这返回到<cd2>D</cd2>重复的位置以下。

<cd2>B</cd2><cd3>C</cd3><cd1>A</cd1><cd2>D</cd2><cd1>E</cd1><cd2>D</cd2>


如何编写xpath来解决以上(3)问题?

请注意,我必须使用Xpath 1.0,因此不可以使用distinct-values函数。另外,我需要获取匹配的节点列表,而不是xpath中的文本值,因为我必须使用AXIOM对这些节点进行更多处理。

更新:我正在使用此xpath获取匹配的元素,然后将使用AXIOM处理这些元素。因此,我需要编写一个xpath表达式以一次性获得匹配的元素(我无法在AXIOM或XSLT中编写自定义流)。另外,由于实名不匹配,因此无法使用cd *。我在这里使用了一个示例。

最佳答案

试试这个:

//cd1[not(text() = preceding::cd1/text())][normalize-space()]|
//cd2[not(text() = preceding::cd2/text())][normalize-space()]|
//cd3[not(text() = preceding::cd3/text())][normalize-space()]

09-26 00:15