Плоская структура с промежутками для вложенных / иерархических с использованием XSLT 1.0 - PullRequest
0 голосов
/ 03 февраля 2019

Да, я знаю некоторые ответы, например, Плоская на вложенную структуру, основанная на значении атрибута с использованием XSLT , но есть разница, которая имеет значение для меня.

Дано следующее плоская структура XML .Информация об уровне может содержать пробелы .Может быть любое количество элементов без информации об уровне между элементами, содержащими информацию об уровне.Такие элементы должны быть назначены предыдущему элементу с указанием уровня.

<doc>
  <item>
    <meta>
        <text>abc</text>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>1</level>
        <title>a</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>2</level>
        <title>b</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>1</level>
        <title>c</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>2</level>
        <title>d</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>2</level>
        <title>e</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>4</level>
        <title>f</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>1</level>
        <title>g</title>
      </para>
    </meta>
  </item>
  <item>
    <meta>
        <text>def</text>
    </meta>
  </item>
  <item>
    <meta>
        <text>ghi</text>
    </meta>
  </item>
  <item>
    <meta>
      <para>
        <level>2</level>
        <title>h</title>
      </para>
    </meta>
  </item>
</doc>

Результат после преобразования должен выглядеть следующим образом ...

<text>abc</text>
<test title="a">
   <test title="b"/>
</test>
<test para="c">
   <test title="d"/>
   <test title="e">
      <test para="f"/>
   </test>
</test>
<test title="g">
    <text>def</text>
    <text>ghi</text>
   <test title="h"/>
</test>

MyПодход к преобразованию заключается в следующем.

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

    <xsl:key name="child" match="item"
    use="generate-id(preceding-sibling::item[(meta/para/level) &lt;= ((current()/meta/para/level) - 1)][1])"/>

    <xsl:template match="/doc">
        <xsl:apply-templates select="item[(meta/para/level) = 1]"/>
    </xsl:template>

    <xsl:template match="item">
        <test title="{meta/para/title}">
            <xsl:apply-templates select="key('child', generate-id())"/>
        </test>
    </xsl:template>

</xsl:stylesheet>

К сожалению, я не могу найти решение.

1 Ответ

0 голосов
/ 03 февраля 2019

Как насчет:

XSLT 1.0

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

<xsl:key name="child1" 
         match="item[meta/para/level]"
         use="generate-id(preceding-sibling::item[meta/para/level &lt; current()/meta/para/level][1])"/>

<xsl:key name="child2" 
         match="item[meta/text]"
         use="generate-id(preceding-sibling::item[meta/para/level][1])"/>

<xsl:template match="/doc">
    <root>
        <xsl:apply-templates select="item[meta/para/level = 1] | key('child2', '')"/>
    </root>
</xsl:template>

<xsl:template match="item[meta/para/title]">
    <test title="{meta/para/title}">
        <xsl:apply-templates select="key('child1', generate-id()) | key('child2', generate-id())"/>
    </test>
</xsl:template>

<xsl:template match="item[meta/text]">
    <text>
        <xsl:value-of select="meta/text"/>
    </text>
</xsl:template>

</xsl:stylesheet>

Я добавил элемент root, чтобы сделать результат правильно сформированным XML.

...