如何编写xpath查询以匹配下面XML代码段中的<subitem>
元素?
具体来说,我想匹配任何具有“name”属性的元素,该属性与根的“name”属性的值相匹配。 <root>
和<subitem>
之间可能存在任意数量的祖先。
<root name="xyz">
<anything>
<subitem name="xyz" />
</anything>
</root>
我的目标是编写一个PMD规则来查找Logger.getLogger()的案例,该案例使用的语句与语句所在的类不同。
答案 0 :(得分:1)
使用此XPath表达式:
//*[@name = /*/@name]
这将选择任何元素(包括名为root
的顶部元素),其name
属性与顶部元素的name
属性具有相同的字符串值。根据提供的XML文档评估此XPath表达式时,会选择两个元素 - root
和subitem
。
我认为只需要这两个元素中的第二个元素。为此,请使用以下XPath表达式:
//*/*[@name = /*/@name]
基于XSLT的验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="//*/*[@name = /*/@name]"/>
========
<xsl:copy-of select="//*[@name = /*/@name]"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<root name="xyz">
<anything>
<subitem name="xyz" />
</anything>
</root>
评估两个XPath表达式,并将选定的节点复制到输出中:
<subitem name="xyz"/>
========
<root name="xyz">
<anything>
<subitem name="xyz"/>
</anything>
</root>
<subitem name="xyz"/>
答案 1 :(得分:0)
//*[@name=(ancestor::*/@name)]
这应该可以解决问题。我会将其读作“查找具有相同name
的祖先的所有节点。”
编辑(加上第二个,仍然选择太多)
编辑问题后:
//*[@name=(/@name)]
这读作“查找与根节点具有相同name
的所有节点。”请注意,根节点可能不是您认为的那样(并且您希望与名为root
的最顶层节点匹配,而不是root),您可能需要将其实现为
//*[@name=(/root/@name)]
或//*[@name=(/*/@name)]
这会选择两个元素,即您不需要的subitem
和root
,您只想选择不是最顶层的节点({{1}的后代})。 Dimitre Novatchev为此致记。
root