我正在尝试使用XPath 1.0从以下xml中识别重复的序列号,然后使用XPathNavigator
在.Net中对其进行评估。
<?xml version="1.0" encoding="utf-16"?>
<Inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>1112</SerialNumber>
</Item>
<Item>
<SerialNumber>1112</SerialNumber>
</Item>
</Items>
</Inventory>
我尝试通过评估此
来做到这一点//Items/Item/SerialNumber
在.Net中的自定义XSLT上下文函数(实现IXsltContextFunction
like this MSDN example)中的表达式,但Invoke函数一次被调用一个结果,因此我无法查看其他结果以查找重复项。
1)有没有办法使用单个XPath 1.0表达式?
OR
2)有没有办法将一个元素数组传递给自定义XSLT上下文函数类的单个Invoke调用?我在VB.Net中工作,但对任何C#都很满意人们可以分享的例子。
谢谢,
加文
修改
感谢O R Mapper和Dimitre的回复。我最初接受了O R Mapper的回复,因为它确实做了我的要求。我已经接受了Dimitre的回答,因为我喜欢它提供了一个独特的值列表。这两个回复都非常有用!
答案 0 :(得分:4)
我要回答 1),所以 2)应该不再重要:
您可以使用preceding-sibling
元素上的<Item>
轴来查找具有相同序列号的任何前面的<Item>
元素。
试试这个(编写它只返回序列号而不是元素 - 如果这不是你想要的,你不知道如何更改结果,请告诉我):
/Inventory/Items/Item/SerialNumber/node()[.=../../preceding-sibling::Item/SerialNumber/node()]
对于您的示例文档,它将返回
1112
答案 1 :(得分:3)
使用强>:
/*/*/Item
[SerialNumber = following-sibling::Item/SerialNumber
and
not(SerialNumber = preceding-sibling::Item/SerialNumber)
]
这为只有Item
子元素且具有相同字符串值的Item
个元素组选择一个SerialNumber
元素。
基于XSLT的验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/*/Item
[SerialNumber = following-sibling::Item/SerialNumber
and
not(SerialNumber = preceding-sibling::Item/SerialNumber)
]"/>
</xsl:template>
</xsl:stylesheet>
对此XML文档应用此转换时(基于提供的转换,但更有趣):
<Inventory>
<Items>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>3333</SerialNumber>
</Item>
</Items>
</Inventory>
转换会评估XPath表达式并将所选节点复制到输出中:
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
最后,如果您只想获得SerialNumber
重复值,请使用:
/*/*/Item
[SerialNumber = following-sibling::Item/SerialNumber
and
not(SerialNumber = preceding-sibling::Item/SerialNumber)
]
/SerialNumber/text()