XPath选择具有Xpath 2.0特定属性的唯一元素列表

时间:2013-08-26 19:05:51

标签: xml xpath

我在获取具有特定属性的唯一元素列表(基于名称)时遇到了一些麻烦。我可以得到其中任何一个列表,但合并列表是什么让我沮丧。我的xml看起来像这样:

<global>
    <discipline name="tracks">
        <group name="Normal"/>
        <group name="Gloss" PackGroup="Diffuse"/>
        <group name="Mask"/>
        <group name="Diffuse"/>
        <group name="Tint" PackGroup="Gloss"/>
    </discipline>
    <discipline name="trains">
        <group name="Mask"/>
        <group name="Diffuse" PackGroup="Mask"/>
    </discipline>
</global>

我可以使用此xpath查询轻松获得一个明确的组元素列表:

/configuration/global/discipline/group[not(@name = following::group/@name)]

并且获取定义了PackGroup属性的组元素列表也是微不足道的:

/configuration/global/discipline/group[@PackGroup]

但是,我似乎无法获得已定义PackGroup属性的唯一元素列表。我试过这个:

/configuration/global/discipline/group[not(@name = following::group/@name) and @PackGroup]
/configuration/global/discipline/group[not(@name = following::group/@name) and contains(@PackGroup, '*')]

不返回任何元素和

/configuration/global/discipline/group[not(@name = following::group/@name) and contains(@PackGroup, '')]

只返回唯一列表。有谁知道正确的xpath查询是什么来获得我正在寻找的东西?

(我正在使用C#和xpath 2.0,以防万一)

谢谢!

2 个答案:

答案 0 :(得分:4)

更有效的解决方案(O(n log n)而不是O(n * n))

for $n in distinct-values(//group[@Packgroup]/@name) 
return (//group[@Packgroup][@name=$n])[1]

答案 1 :(得分:1)

我认为您正在寻找的是

/configuration/global/discipline/group
  [not(@name = following::group[@Packgroup]/@name) and @PackGroup]

您要确保您要过滤的组(表达式中的第一个group)和您正在检查的以下组(第二个group)都有@ Packgroup属性。

使用distinct-values()函数可能还有一种方法可以做到这一点,但我现在还没想过。