Суммирование значений рекурсивных функций в XSLT - PullRequest
2 голосов
/ 23 июня 2010

У меня есть XML вроде этого:

 <assessment name="Assessment">
  <section name="Section1">
   <item name="Item1-1"/>
   <item name="Item1-2"/>
   <item name="Item1-3"/>
   <item name="Item1-4"/>
   <item name="Item1-5"/>
  </section>
  <section name="Section2">
   <item name="Item2-1"/>
   <item name="Item2-2"/>
   <item name="Item2-3"/>
   <section name="Section2-2">
    <item name="Item2-2-1"/>
    <item name="Item2-2-2"/>
    <item name="Item2-2-3"/>
    <item name="Item2-2-4"/>
   </section>
  </section>
 </assessment>

Как видите, оценка может содержать разделы.Раздел может содержать разделы и / или элементы.

Я хочу использовать XSLT для рекурсивного подсчета количества элементов в оценках и разделах.Итак, мое преобразование должно вывести что-то вроде этого:

Assessment: 12 items
Section1:    5 items
Section2:    7 items
Section2-2:  4 items

У меня есть начало с этим рекурсивным XSLT:

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

 <output method="text"/>

 <template match="/assessment">
  <xsl:for-each select="section">
   <xsl:call-template name="sectionCount">
   </xsl:call-template>
  </xsl:for-each>
 </template>

 <template name="sectionCount">
  <xsl:variable name="items" select="item"/>
   <xsl:for-each select="section">
     <xsl:call-template name="sectionCount">
     </xsl:call-template>
   </xsl:for-each>
  <xsl:value-of select="count($items)"/>
 </template>
</stylesheet>

Что я не могу понять, как это сделать, это передатьценности резервное копирование и добавить их.Как это сделать, точно?

Ответы [ 2 ]

1 голос
/ 23 июня 2010

Чтобы ответить на ваш вопрос: вы заключаете вызов шаблона (ов) в объявление переменной.

<xsl:variable name="result">
  <!-- call or apply templates here -->
  <xsl:call-template name="my-template"/>
</xsl:variable>
<!-- use the defined value: -->
<xsl:copy-of select="$result"/>

Однако в вашем случае есть лучший способ получить общее количество элементов сколь угодно глубокимво вложенной структуре: используйте подстановочные знаки XPath:

<xsl:value-of select="count(.//item)"/>

Вы можете использовать это так:

<xsl:template match="assessment|section">
   <!-- output section subtotal -->
   <!-- print name : number-of-items, adapt to get the proper section name -->
   <xsl:value-of select="concat(@name, ': ', count(.//item))"/>
   <!-- recurse: sub sections will get their subtotals listed, too -->
   <xsl:apply-templates select="*"/>
</xsl:template>
0 голосов
/ 23 июня 2010

Вот решение XSLT 2.0

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my"
 >
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

    <xsl:template match="assessment|section">
      <xsl:value-of select="concat(@name, ': ', my:sumItems(.), ' items&#xA;')"/>
      <xsl:apply-templates/>
    </xsl:template>

    <xsl:function name="my:sumItems" as="xs:integer*">
      <xsl:param name="pNode" as="element()"/>

      <xsl:sequence select="count($pNode/item) + sum($pNode/section/my:sumItems(.))"/>
    </xsl:function>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<assessment name="Assessment">
    <section name="Section1">
        <item name="Item1-1"/>
        <item name="Item1-2"/>
        <item name="Item1-3"/>
        <item name="Item1-4"/>
        <item name="Item1-5"/>
    </section>
    <section name="Section2">
        <item name="Item2-1"/>
        <item name="Item2-2"/>
        <item name="Item2-3"/>
        <section name="Section2-2">
            <item name="Item2-2-1"/>
            <item name="Item2-2-2"/>
            <item name="Item2-2-3"/>
            <item name="Item2-2-4"/>
        </section>
    </section>
</assessment>

желаемый, правильный результат получается :

Assessment: 12 items
Section1: 5 items
Section2: 7 items
Section2-2: 4 items

В то время как в этой конкретной задаче можно использовать простое выражение XPath (count(.//item)), это решение демонстрирует общий и полезный шаблон для задач, которые не допускают такого немедленного вычисления .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...