具有与祖先相同属性值的项的Xpath

时间:2012-06-28 20:00:11

标签: java xml xpath substitution pmd

如何编写xpath查询以匹配下面XML代码段中的<subitem>元素?

具体来说,我想匹配任何具有“name”属性的元素,该属性与根的“name”属性的值相匹配。 <root><subitem>之间可能存在任意数量的祖先。

<root name="xyz">
  <anything>
    <subitem name="xyz" />
  </anything>
</root>

我的目标是编写一个PMD规则来查找Logger.getLogger()的案例,该案例使用的语句与语句所在的类不同。

2 个答案:

答案 0 :(得分:1)

使用此XPath表达式

//*[@name = /*/@name]

这将选择任何元素(包括名为root的顶部元素),其name属性与顶部元素的name属性具有相同的字符串值。根据提供的XML文档评估此XPath表达式时,会选择两个元素 - rootsubitem

我认为只需要这两个元素中的第二个元素。为此,请使用以下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)]


这会选择两个元素,即您不需要的subitemroot,您只想选择不是最顶层的节点({{1}的后代})。 Dimitre Novatchev为此致记。

root