0

属性値に基づいて兄弟を子としてグループ化するエレガントな方法が必要です。これは、「colspan」属性に基づいて html テーブルを階層データに変換することに似ています。

入力構造には、データを含む子ノードを持つ複数の兄弟ノードがあります。ただし、データ ノードには、階層的な優位性を示すレベル属性が含まれる場合があります。

入力

<root>
  <Sibling>
    <Data level="4">ABC</Data>
  </Sibling>
  <Sibling>
    <Data level="3">fff</Data>
  </Sibling>
  <Sibling>
    <Data>8000</Data>
    <Data>01/04/2013</Data>
  </Sibling>
  <Sibling>
    <Data level="3">ggg</Data>
  </Sibling>
  <Sibling>
    <Data>2000</Data>
    <Data>01/05/2013</Data>
  </Sibling>
  <Sibling>
    <Data level="4">DEF</Data>
  </Sibling>
  <Sibling>
    <Data level="3">iii</Data>
  </Sibling>
  <Sibling>
    <Data>2000</Data>
    <Data>01/22/2013</Data>
  </Sibling>
  <Sibling>
    <Data level="4">GHI</Data>
  </Sibling>
  <Sibling>
    <Data level="3">mmm</Data>
  </Sibling>
  <Sibling>
    <Data>4000</Data>
    <Data>07/05/2011</Data>
  </Sibling>
  <Sibling>
    <Data level="3">nnn</Data>
  </Sibling>
  <Sibling>
    <Data>6000</Data>
    <Data>01/07/2011</Data>
  </Sibling>
</root>

level 属性を使用して、以下に示すように、兄弟を移動して子にする必要があります。

出力

<Main>
  <Group>
    <Data level="4">ABC</Data>
    <Subgroup>
      <Data level="3">fff</Data>
      <Child>
        <Data>8000</Data>
        <Data>01/04/2013</Data>
      </Child>
    </Subgroup>
    <Subgroup>
      <Data level="3">ggg</Data>
      <Child>
        <Data>2000</Data>
        <Data>01/05/2013</Data>
      </Child>
    </Subgroup>
  </Group>
  <Group>
    <Data level="4">DEF</Data>
    <Subgroup>
      <Data level="3">iii</Data>
      <Child>
        <Data>2000</Data>
        <Data>01/22/2013</Data>
      </Child>
    </Subgroup>
  </Group>
  <Group>
    <Data level="4">GHI</Data>
    <Subgroup>
      <Data level="3">mmm</Data>
      <Child>
        <Data>4000</Data>
        <Data>07/05/2011</Data>
      </Child>
    </Subgroup>
    <Subgroup>
      <Data level="3">nnn</Data>
      <Child>
        <Data>6000</Data>
        <Data>01/07/2011</Data>
      </Child>
    </Subgroup>
  </Group>
</Main>

私が開発したスタイル シートはあまり洗練されておらず、レベルの値を仮定しています。ロジックとレベル値に基づいて開始タグと終了タグを出力して親ノードを作成します。ノードを渡して子を追加したいのですが、これが行われた例が見つかりません。これを行うためのよりエレガントな方法はありますか?

スタイルシート

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

  <xsl:output method="xml"  indent="yes" omit-xml-declaration="yes" />

  <xsl:variable name="group_begin">&lt;Group&gt;</xsl:variable>
  <xsl:variable name="subgroup_begin">&lt;Subgroup&gt;</xsl:variable>
  <xsl:variable name="group_end">&lt;/Group&gt;</xsl:variable>
  <xsl:variable name="subgroup_end">&lt;/Subgroup&gt;</xsl:variable>

  <xsl:template match="/">
    <Main>
      <xsl:apply-templates select="root" />
    </Main>
  </xsl:template>

  <xsl:template match="root">
    <xsl:for-each select="Sibling">
      <xsl:choose>
        <xsl:when test="Data[not(@level)]">
          <xsl:call-template name="Sibling">
            <xsl:with-param name="level" select="0"/>
            <xsl:with-param name="next_level" select="following-sibling::*[1]/Data/@level"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="Sibling">
            <xsl:with-param name="level" select="Data/@level"/>
            <xsl:with-param name="next_level" select="0"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
    <xsl:value-of disable-output-escaping="yes" select="$group_end"/>
  </xsl:template>

  <xsl:template name="Sibling">
    <xsl:param name="level"  />
    <xsl:param name="next_level"/>
    <xsl:choose>
      <xsl:when test="$level = '4'">
        <xsl:value-of disable-output-escaping="yes" select="$group_begin"/>
        <xsl:copy-of select="*"/>
      </xsl:when>
      <xsl:when test="$level = '3'">
        <xsl:value-of disable-output-escaping="yes" select="$subgroup_begin"/>
        <xsl:copy-of select="*"/>
      </xsl:when>
      <xsl:otherwise>
        <Child>
        <xsl:copy-of select="*"/>
        </Child>
        <xsl:value-of disable-output-escaping="yes" select="$subgroup_end"/>
        <xsl:if test="$next_level = 4">
          <xsl:value-of disable-output-escaping="yes" select="$group_end"/>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

ここで、属性に基づいて兄弟ノードをラップする手法の使用を検討しましたが、属性レベルは実際には相対値であり、固定されていません。

4

1 に答える 1

0

ここで XSLT 2.0 を使用して解決された同様の問題があります: http://www.saxonica.com/papers/ideadb-1.1/mhk-paper.xml

これを絶対に XSLT 1.0 にする必要がありますか? それはより困難ですが、決して不可能ではありません。基本的に、特定のノードのテンプレート ルールがその直後の兄弟にテンプレートを適用する「兄弟再帰」の手法を習得する必要があります。「兄弟再帰」を検索すると、いくつかのアイデアが生まれるかもしれません。

于 2013-10-16T22:09:05.047 に答える