我正在尝试在多个不同节点中的多个属性中搜索某些内容
这是我在一个属性中找到它的方式
//*[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。关于如何做到这一点的任何想法?尝试了除重复包含但不起作用之外的几种方法。
答案 0 :(得分:5)
这对我有用
/cars/car/@*[contains(.,'KEYA')]/parent::*
好的,在编辑之后,我建议
/cars/car/@*[name()!='dontmatch'][contains(.,'KEYA')]/parent::*
如果要排除多个属性,则需要指定其他谓词(方括号内的内容)。 Xpath不提供排除attr名称集的方法,除非您可以使用startswith()
或contains()
或类似的东西约束集合。
有一些方便的方法可以在其他库中查询XML,例如,如果您使用的是.NET,则可以使用LINQ-to-XML。这将允许您更加简洁地指定这些类型的查询。但它完全是一个不同的API。
答案 1 :(得分:3)
使用强>:
/*/*[@*
[contains('|name|name1|name2|name3|name4|',
concat('|',name(),'|')
)
and
contains(., 'KEYA')
]
]
以下是由the XPath Visualizer 生成的选择:
<强>解释强>:
您可以在字符串中指定要搜索的所有属性的名称。使用的“管道分隔符(|
”保证即使名称是另一个名称的开头,如果该名称有一个单独的,以管道分隔的子字符串,它也只会包含在搜索中。
答案 2 :(得分:1)
怎么样:
//*[contains(@name,'KEYA') or contains(@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') and contains('name,name2', local-name())]/parent::**