【问题标题】:XPATH query to find attributes that contains a keywordXPATH 查询以查找包含关键字的属性
【发布时间】:2011-08-30 06:28:08
【问题描述】:

我正在尝试在多个不同节点的多个属性中搜索某些内容

这就是我在一个属性中找到它的方式

//*[contains(@name,'KEYA')]

示例 XML:

<cars>

<car model="2000" name="Awesome KEYA Car" name2="somethine else">Brand1</car>
<car model="2005" name="Awesome Car" name2="KEYA something else">Brand 2</car>
<car name="Awesome Car" name2="somethine else">Brand1</car>
<car dontmatch="KEYA" name2="somethine else">Brand3333</car>

</cars>

我真正想要的是超过 10 个属性(它只需要匹配白名单属性),

//*[contains((@name or @name2 or @name3),'KEYA')]

使用 XPATH 1.0。关于如何做到这一点的任何想法?除了重复包含之外,尝试了几种方法,但没有奏效。

【问题讨论】:

  • 好问题,+1。请参阅我的答案以获得完整、简短且简单的单行 XPath 表达式解决方案,它使您可以灵活地以最紧凑和自然的形式轻松指定要搜索的属性的名称。还提供了解释。

标签: .net xpath attributes contains


【解决方案1】:

这对我有用

/cars/car/@*[contains(.,'KEYA')]/parent::*

好的,修改后,我建议

/cars/car/@*[name()!='dontmatch'][contains(.,'KEYA')]/parent::*

如果要排除多个属性,则需要指定附加谓词(方括号内的内容)。 Xpath 不提供排除 attr 名称集的方法,除非您可以使用 startswith()contains() 或类似名称来约束该集。

有一些方便的方法可以在其他库中查询 XML,例如,如果您使用的是 .NET,则可以使用 LINQ-to-XML。这将允许您更简洁地指定这些类型的查询。但它完全是一个不同的 API。

【讨论】:

  • 它只需要在某些属性列表中找到,而不是全部
  • 回复:“Xpath 没有提供方法……”。来吧,你为什么这么肯定? :) 其他解决方案证明这种说法是错误的。更不用说 XPath 2.0。至于所谓的“XPath 可视化器”,我想知道它什么时候才能获得我自己的、更老的、同名的工具的所有功能——或者这只是我的一厢情愿?
  • Dimitre,休息一下。请。您对我的一个答案或帖子发表的每一条评论都是敌对的、对抗的或批评的。没有必要这样做。我不知道你为什么对我有如此私人的敌意。没有理由。请停下。很抱歉重复使用您构建的工具的名称。这并不是一种侮辱。请放松。
【解决方案2】:

使用

/*/*[@*
        [contains('|name|name1|name2|name3|name4|',
                  concat('|',name(),'|')
                  )
       and
         contains(., 'KEYA')
        ]
       ]

这是由the XPath Visualizer制作的选择

解释

您可以在字符串中指定要搜索的所有属性的名称。使用的“管道分隔符 (|) 保证即使名称是另一个名称的开头,它也只会在该名称有单独的管道分隔子字符串时包含在搜索中。

【讨论】:

  • 不错,已将其标记为完整,感谢您的解释。
  • /*/*//*有区别吗?
  • @dr. evil: 是的,/*/* 选择 XML 文档顶部元素的所有子元素,而//* 选择文档中的所有元素。
【解决方案3】:

怎么样:

//*[包含(@name,'KEYA') 或包含(@name2,'KEYA')]

您可以接受 Cheeso 的回答并执行以下操作:

/cars/car/@*[contains(.,'KEYA') and local-name() != 'dontmatch']/parent::*

您将不得不以一种或另一种方式构建 XPath 语句,以从属性白名单中进行选择(我的示例),或排除黑名单中的属性(修改后的 Cheeso 示例)。

从 Cheeso 的工作中重新构建,这可能会简化黑名单的构建:

//@*[contains(.,'KEYA') and not(contains('dontmatch,dontmatch2', local-name()))]/parent::*

或作为白名单:

//@*[contains(.,'KEYA') 和 contains('name,name2', local-name())]/parent::**

【讨论】:

  • 是的,这将解决问题,但管理起来真的很丑:)
  • @dr.邪恶 - 我可能同意,@cheeso 的解决方案如果您搜索 所有 属性会更好。
  • @Kev 我没有搜索所有内容
  • 谢谢,我希望能找到类似“contains((@name or @name2 or @name3),'KEYA')”的东西,但我想我必须把包含这么多的东西列入白名单
  • @dr.没有/parent::* 的邪恶你只会选择属性节点,/parent::* 选择包含属性的父 XML 节点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多