我有一个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()]