1

我将如何编写一个 xpath 查询来匹配<subitem>下面 XML 片段中的元素?

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

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

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

4

2 回答 2

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"/>
于 2012-06-29T04:14:57.473 回答
0

//*[@name=(ancestor::*/@name)]

这应该可以解决问题。我会将其读作“查找所有具有相同祖先的节点name。”


编辑(加上第二个,它仍然选择了太多)

编辑问题后:

//*[@name=(/@name)]

name这读作“查找与根节点相同的所有节点”。请注意,根节点可能不是您认为的那样(并且您希望与名为 的最顶层节点匹配root,而不是root),您可能需要将其实现为

//*[@name=(/root/@name)]或者//*[@name=(/*/@name)]


这选择了两个元素,你的subitemroot不需要的,你只想选择不是最顶层的节点(是 的后代root)。这要归功于 Dimitre Novatchev。

//*/*[@name=(/*/@name)]

于 2012-06-28T20:10:44.457 回答