Подсчет предыдущих атрибутов с определенным значением в XSLT - PullRequest
1 голос
/ 08 февраля 2012

Я заранее прошу прощения, если это неправильно отформатировано, но ...

Мне нужно взять следующий 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, а не количество атрибутов внутри себя, которые установлены в "?".

Было бы хорошо, если бы мне не пришлось писать рекурсив?счетчик ...

Ответы [ 4 ]

2 голосов
/ 08 февраля 2012

Мне кажется, что простейшее решение выглядит следующим образом и дает желаемый результат:

<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 голос
/ 08 февраля 2012

Это выражение вам нужно?

<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
0 голосов
/ 08 февраля 2012

Различные настройки, поэтому может потребоваться рестайлинг для использования в 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
0 голосов
/ 08 февраля 2012

Знак вопроса - это специальный символ в XPath, его следует заменить на объект XML.Вы должны использовать text(), чтобы проверить значение ваших атрибутов.

(На самом деле, я не уверен насчет знака вопроса, так как он находится внутри строки. Это может быть не нужно или даже вредно ...)

Попробуйте что-то вроде этого:

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