XSLT: превратить плоский список в иерархию - PullRequest
2 голосов
/ 07 февраля 2012

Я пытаюсь понять функции группировки в XSLT 2.0.Мой исходный документ -

<root>
  <entry level="a" name="aaa"/>
  <entry level="a" name="bbb"/>
  <entry level="b" name="ccc"/>
  <entry level="c" name="ddd"/>
  <entry level="a" name="eee"/>
  <entry level="a" name="fff"/>
  <entry level="b" name="ggg"/>
</root>

, и результат должен выглядеть примерно так:

<section name="aaa"/>
<section name="bbb">
  <section name="ccc">
    <section name="ddd" />
  </section>
</section>
<section name="eee"/>
<section name="fff">
  <section name="ggg" />
</section>

То есть: если есть следующая запись с более глубоким уровнем (b глубже, чем a ,....) следующий раздел должен быть дочерним по отношению к текущему, если это тот же уровень, то это должен быть следующий родной брат.

Я пробовал с xsl:group-by select="entry" group-by="@level", что дает мне разумную группировку, но яне знаю, как открыть раздел, чтобы идти вниз, если есть спад.

Есть другой похожий вопрос , который гласит, что «В XSLT 2.0 было бы довольно легко сновые функции группировки. "- это может быть легко, но я не понимаю.

1 Ответ

3 голосов
/ 07 февраля 2012

Вот пример:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf"
  version="2.0">

  <xsl:output indent="yes"/>

  <xsl:function name="mf:group" as="element(section)*">
    <xsl:param name="entries" as="element(entry)*"/>
    <xsl:param name="level" as="xs:string"/>
    <xsl:for-each-group select="$entries" group-starting-with="entry[@level = $level]">
      <section name="{@name}">
        <xsl:sequence select="mf:group(current-group() except ., codepoints-to-string(string-to-codepoints($level)[1] + 1))"/>
      </section>
    </xsl:for-each-group>
  </xsl:function>

  <xsl:template match="root">
    <xsl:copy>
      <xsl:sequence select="mf:group(entry, 'a')"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Должен работать с любыми уровнями от 'a' до 'z'.

Саксонский 9,4, когда работает выше против

<root>
  <entry level="a" name="aaa"/>
  <entry level="a" name="bbb"/>
  <entry level="b" name="ccc"/>
  <entry level="c" name="ddd"/>
  <entry level="a" name="eee"/>
  <entry level="a" name="fff"/>
  <entry level="b" name="ggg"/>
</root>

выходы

<root>
   <section name="aaa"/>
   <section name="bbb">
      <section name="ccc">
         <section name="ddd"/>
      </section>
   </section>
   <section name="eee"/>
   <section name="fff">
      <section name="ggg"/>
   </section>
</root>
...