使用XSLT中的特定值计算先前的属性

时间:2012-02-08 08:01:02

标签: xml xslt xpath wildcard

如果格式不正确,我会提前道歉,但是......

我需要使用以下xml:

<box r="?" c="?" b="?">
  <h r="?" b="2">
    <u>
      <v c="5" b="2">
        <l>
          <h r="?" b="1"/>
        </l>
        <r>
          <v c="?" b="?"/>
        </r>
      </v>
    </u>
    <d>
      <h r="?" b="2"/>
    </d>
  </h>
</box>

并使用xslt:

<xsl:template name="BoxVariables-Count">
  <xsl:text>
        // Counting...</xsl:text>

  <xsl:apply-templates select="descendant::*[@* = &quot;?&quot;]" mode="box-variable-count"/>
</xsl:template>

<xsl:template match="local:*" mode="box-variable-count">
  <xsl:variable name="position" select="position()"/>
  <xsl:text>
        // </xsl:text></xsl:text><xsl:value-of select="local-name()"/>
  <xsl:text> = </xsl:text>
  <xsl:value-of select="count((ancestor::local:box[1]/descendant-or-self::*[@* = &quot;?&quot;][position() &lt; $position + 1])/@*[@* = &quot;?&quot;])"/>
</xsl:template>

计算“?”的数量在box元素中当前节点之前发生的属性条目。 (注意:“?”实际上是“未知”)

以下行输出当前节点之前包含“?”的节点内的属性总数:

<xsl:value-of select="count((ancestor::local:box[1]/descendant-or-self::*[@* = &quot;?&quot;][position() &lt; $position + 1])/@*)"/>

输出:

  // h = 3
  // h = 5
  // v = 7
  // h = 9

但是,我只想算“?”的数量该集合中的属性。

<xsl:value-of select="count((ancestor::local:box[1]/descendant-or-self::*[@* = &quot;?&quot;][position() &lt; $position + 1])/@*[@* = &quot;?&quot;])"/>

输出:

  // h = 0
  // h = 0
  // v = 0
  // h = 0

我希望:

  // h = 3
  // h = 4
  // v = 5
  // h = 7

换句话说:

count(./@*[@* = &quot;?&quot;])

似乎返回0而不是self中属于“?”的属性数。

如果我不必编写递归会很好吗?计数器...

4 个答案:

答案 0 :(得分:2)

以下似乎是最简单的解决方案,并提供了所需的输出:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="box//*[@*='?']">
  <xsl:value-of select="'&#xa;//', name(), ' = ', 
     count((ancestor::*|preceding::*)/@*[.='?'])"/>
  <xsl:apply-templates/>
</xsl:template>

<xsl:strip-space elements="*"/>

</xsl:stylesheet>

答案 1 :(得分:1)

这是你需要的表达吗?

<xsl:value-of 
   select="count(preceding::*/@*[. = '?']) + count(ancestor::*/@*[. = '?'])"/>

那么,接下来是XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text"/>

   <xsl:template match="*[@*='?']">
      <xsl:value-of select="concat('// ', local-name(), ' = ')"/>
      <xsl:value-of 
         select="count(preceding::*/@*[. = '?']) + count(ancestor::*/@*[. = '?'])"/>
      <xsl:value-of select="'&#13;'"/>
      <xsl:apply-templates/>
   </xsl:template>

   <xsl:template match="/box">
      <xsl:text>// Counting...&#13;</xsl:text>
      <xsl:apply-templates/>
   </xsl:template>
</xsl:stylesheet>

应用于XML时,输出以下内容:

// Counting...
// h = 3
// h = 4
// v = 5
// h = 7

答案 2 :(得分:0)

不同的设置可能需要在xslt中使用重定名,但要达到正确的结果:

<xsl:template match="/box">
    <xsl:variable name="qs" select="descendant-or-self::*[@*='?']"/>
    <xsl:for-each select="$qs[not(local-name()='box')]">
        <xsl:variable name="position" select="position()"/>
        <xsl:value-of select="local-name()"/>
        <xsl:text> = </xsl:text>
        <xsl:value-of select="count(($qs[position() &lt; $position])/@*[.='?'])"/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
</xsl:template>

结果

h = 3
h = 4
v = 5
h = 7

答案 3 :(得分:-2)

问号是XPath中的特殊字符,您应该将其替换为XML实体。您应该使用text()来检查属性的值。

(实际上,我不确定问号,因为它在一个字符串中。它可能没有必要甚至是有害的......)

尝试这样的事情:

count(@*[text() = '&#63;'])