【问题标题】:XPath expression - help neededXPath 表达式 - 需要帮助
【发布时间】:2010-08-04 08:19:47
【问题描述】:

我有这样的示例 XML:

<users>
    <user name="user1">
        <roles separator=",">ADM,USER</roles>
    </user>
    <user name="user2">
        <roles separator=",">ADM,GUEST</roles>
    </user>
    <user name="user3">
        <roles separator=",">READER,GUEST</roles>
    </user>
</users>

有没有什么方法可以使用 XPath 表达式 让所有 用户 担任 GUEST 角色?

【问题讨论】:

  • 好问题 (+1)。有关简短而正确的 XPath 1.0 单行代码,请参阅我的答案。 :)
  • 我已经修复了@Per-T 发现的一个问题——现在我的回答提供了一个非常好的 XPath 1.0 解决方案。

标签: xml xpath


【解决方案1】:

此 XPath 表达式将选择角色节点包含 GUEST 的所有用户。

//user[contains(roles, 'GUEST')]

参见contains xpath 函数。

【讨论】:

  • 我想你应该说,如果没有其他角色有“GUEST”作为一部分,比如它被评论的“EXTERNALGUEST”,那么这个方法是有效的。
【解决方案2】:

使用

/users/user/[roles[contains(concat(@separator, ., @separator), 
                            concat(@separator, 'GUEST', @separator)
                           )
                  ]
            ]

这将选择所有需要的user 节点,无论'GUEST' 是唯一角色还是位于字符串的开头、中间或结尾

【讨论】:

  • 我相信你真的是:/users/user[roles[contains(concat(@separator, ., @separator), concat(@separator, 'GUEST', @separator))]]/@name 因为你的 XPath 坏了。但无论如何我都会给你+1,因为我没有想出这个主意......;)
  • @Per-T:感谢您注意到这一点——昨天回复时我非常疲倦和困倦...... :(
  • +1 很好的答案!我原以为你会带上这样聪明的东西。
【解决方案3】:

如果您能够使用 XSLT 2.0,我建议您对角色字符串进行标记。使用contains() 很好,只要您没有开始使用“EXTERNALGUEST”之类的角色名称或类似名称,因为它也会匹配。

/users/user[tokenize(roles, roles/@separator) = 'GUEST']/@name

此 XPath 将根据 @separator 标记 roles 并返回具有此角色的用户。

【讨论】:

  • 不幸的是,我在尝试将 tokenize 函数与 c# 一起使用时出错。
  • 哦,我相信如果你要在 C# 中实现它,你需要使用 XSLT 1.0。如果您不想使用 Saxon .Net。我认为在 1.0 中用简单的 XPath 表达式解决这个问题是不可能的,但我很高兴被证明是错误的。但是,可以在 XSLT 1.0 中使用递归模板来解决。
猜你喜欢
  • 2019-01-31
  • 1970-01-01
  • 2012-11-30
  • 2011-05-09
  • 2023-03-19
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多