选择没有XSLT/XPath密钥的节点

Dan*_*umb 3 xslt xpath

我正在使用Muenchian方法对XML文档中的节点进行分组.

作为输出的一部分,我想选择我没有分配密钥的所有节点.

我试过了

<xsl:apply-templates select="*[key('kcWWPN','')]"/>
Run Code Online (Sandbox Code Playgroud)

但这似乎没有正常工作,因为它没有选择任何节点.

有关正确方法的任何建议吗?

Dim*_*hev 5

作为输出的一部分,我想选择我没有分配密钥的所有节点.

好问题,+ 1.

以下是两种不同但简单的解决方案:

为简单起见,我假设我们只键入元素,但下面的两个解决方案自然可以扩展到其他类型的节点.

I.简单地说,定义一个 反键:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kDByClass" match="d" use="@class"/>

 <xsl:key name="kCounterKey" match="*[not(self::d)]" use="."/>

 <xsl:template match="*[key('kCounterKey', .)]">
  Counter Keyed: <xsl:value-of select="name()"/>

  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当此转换应用于以下XML文档时(从@lwburk借用):

<root>
    <d class="test">1</d>
    <d class="test">2</d>
    <d class="something">1</d>
    <q>3</q>
</root>
Run Code Online (Sandbox Code Playgroud)

产生了想要的正确结果:

  Counter Keyed: root
  Counter Keyed: q
Run Code Online (Sandbox Code Playgroud)

II.使用所有元素和所有键控元素的集合差异(后者使用Muenchian分组找到):

这个解决方案比第一个简单,因为不需要组成一个反键:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kDByClass" match="d" use="@class"/>

 <xsl:key name="kCounterKey" match="*[not(self::d)]" use="."/>

 <xsl:variable name="vKeyedValues" select=
 "//*[generate-id()
     = generate-id(key('kDByClass', @class)[1])
     ]
      /@class
  "/>

  <xsl:variable name="vKeyedElements" select=
   "key('kDByClass', $vKeyedValues)"/>

  <xsl:variable name="vNonKeyedElements" select=
  "//*[not(count(.|$vKeyedElements) = count($vKeyedElements))]
  "/>

 <xsl:template match="/">
  <xsl:for-each select="$vNonKeyedElements">
    Not Keyed: <xsl:value-of select="name()"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当此转换应用于同一XML文档(上面)时,再次生成相同的正确结果:

Not Keyed: root
Not Keyed: q
Run Code Online (Sandbox Code Playgroud)

注意:当密钥不是节点时,最后一个解决方案可能不起作用,但是函数的结果可能不起作用,例如substring-before().在这种情况下,我们只需修改原始密钥,因此它的use属性就是:use="."并将此解决方案与修改后的原始密钥一起使用.可以证明这个过程产生了正确的,想要的元素集.