2

「XML スプレッドシート 2003 (*.xml)」として保存するときに Excel が生成するものに基づいた XML ドキュメントがあります。

スプレッドシート自体には、ラベルの階層を持つヘッダー セクションが含まれています。

| | ABCDEFGHI
--+------------------------------------------------ -----
1| a1 a2
2| a11 a12 a13 a21 a22
3| a111 a112 a121 a122 a131 a132 a221 a222

この階層はワークブックのすべてのシートに存在し、ほぼどこでも同じように見えます。

Excel XML は、通常の HTML テーブルとまったく同じように機能します。(<row>を含む<cell>)。私はすべてをそのようなツリー構造に変換することができました:

<node title="a1" col="1">
  <node title="a11" col="1">
    <node title="a111" col="1"/>
    <node title="a112" col="2"/>
  </node>
  <node title="a12" col="3">
    <node title="a121" col="3" />
    <node title="a122" col="4" />
  </node>
  <!-- and so on -->
</node>

しかし、ここに複雑さがあります:

  • 複数のワークシートがあるため、それぞれにツリーがあります
  • 階層は各シートでわずかに異なる場合があり、ツリーは等しくありません (たとえば、シート 2 には "a113" があり、他のシートにはありません)。
  • ツリーの深さは明示的に制限されていません
  • ただし、ラベルはすべてのシートで同じであることを意図しているため、グループ化に使用できます

これらの別々のツリーを次のようなものにマージしたいと思います。

<node title="a1">
  <col on="sheet1">1</col>
  <col on="sheet2">1</col>
  <node title="a11">
    <col on="sheet1">1</col>
    <col on="sheet2">1</col>
    <node title="a111">
      <col on="sheet1">1</col>
      <col on="sheet2">1</col>
    </node>
    <node title="a112">
      <col on="sheet1">2</col>
      <col on="sheet2">2</col>
    </node>
    <node title="a113"><!-- different here -->
      <col on="sheet2">3</col>
    </node>
  </node>
  <node title="a12">
    <col on="sheet1">3</col>
    <col on="sheet2">4</col>
    <node title="a121">
      <col on="sheet1">3</col>
      <col on="sheet2">4</col>
    </node>
    <node title="a122">
      <col on="sheet1">4</col>
      <col on="sheet2">5</col>
    </node>
  </node>
  <!-- and so on -->
</node>

理想的には、Excel XML から 3 つの構造を構築する前に、マージを実行できるようにしたいと考えています (これを開始していただければ、それは素晴らしいことです)。しかし、これをどのように行うのか見当がつかないので、ツリーが構築された後のマージ (つまり、上記の状況) は問題ありません。

御時間ありがとうございます。:)

4

2 に答える 2

2

XSLT 1.0 で考えられる解決策の 1 つを次に示します

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="/*">
      <t>
        <xsl:apply-templates
           select="node[@title='a1'][1]">
          <xsl:with-param name="pOther"
            select="node[@title='a1'][2]"/>
        </xsl:apply-templates>
      </t>
    </xsl:template>

    <xsl:template match="node">
      <xsl:param name="pOther"/>

      <node title="{@title}">
        <col on="sheet1">
          <xsl:value-of select="@col"/>
        </col>
          <xsl:choose>
            <xsl:when test="not($pOther)">
              <xsl:apply-templates mode="copy">
                <xsl:with-param name="pSheet" select="'sheet1'"/>
              </xsl:apply-templates>
            </xsl:when>
            <xsl:otherwise>
              <col on="sheet2">
                <xsl:value-of select="$pOther/@col"/>
              </col>
              <xsl:for-each select=
                "node[@title = $pOther/node/@title]">

                <xsl:apply-templates select=".">
                  <xsl:with-param name="pOther" select=
                   "$pOther/node[@title = current()/@title]"/>
                </xsl:apply-templates>
              </xsl:for-each>

              <xsl:apply-templates mode="copy" select=
                "node[not(@title = $pOther/node/@title)]">
                <xsl:with-param name="pSheet" select="'sheet1'"/>
              </xsl:apply-templates>

              <xsl:apply-templates mode="copy" select=
                "$pOther/node[not(@title = current()/node/@title)]">
                <xsl:with-param name="pSheet" select="'sheet2'"/>
              </xsl:apply-templates>
            </xsl:otherwise>
          </xsl:choose>
      </node>
    </xsl:template>

    <xsl:template match="node" mode="copy">
      <xsl:param name="pSheet"/>

      <node title="{@title}">
        <col on="{$pSheet}">
          <xsl:value-of select="@col"/>
        </col>

        <xsl:apply-templates select="node" mode="copy">
          <xsl:with-param name="pSheet" select="$pSheet"/>
        </xsl:apply-templates>
      </node>
    </xsl:template>
</xsl:stylesheet>

上記の変換がこの XML ドキュメントに適用されると(共通の最上位ノードの下にある 2 つの XML ドキュメントの連結 -- 読者の演習として残しておきます :) ):

<t>
    <node title="a1" col="1">
        <node title="a11" col="1">
            <node title="a111" col="1"/>
            <node title="a112" col="2"/>
        </node>
        <node title="a12" col="3">
            <node title="a121" col="3" />
            <node title="a122" col="4" />
        </node>
        <!-- and so on -->
    </node>
    <node title="a1" col="1">
        <node title="a11" col="1">
            <node title="a111" col="1"/>
            <node title="a112" col="2"/>
            <node title="a113" col="3"/>
        </node>
        <node title="a12" col="4">
            <node title="a121" col="4" />
            <node title="a122" col="5" />
        </node>
        <!-- and so on -->
    </node>
</t>

必要な結果が生成されます。

<t>
    <node title="a1">
        <col on="sheet1">1</col>
        <col on="sheet2">1</col>
        <node title="a11">
            <col on="sheet1">1</col>
            <col on="sheet2">1</col>
            <node title="a111">
                <col on="sheet1">1</col>
                <col on="sheet2">1</col>
            </node>
            <node title="a112">
                <col on="sheet1">2</col>
                <col on="sheet2">2</col>
            </node>
            <node title="a113">
                <col on="sheet2">3</col>
            </node>
        </node>
        <node title="a12">
            <col on="sheet1">3</col>
            <col on="sheet2">4</col>
            <node title="a121">
                <col on="sheet1">3</col>
                <col on="sheet2">4</col>
            </node>
            <node title="a122">
                <col on="sheet1">4</col>
                <col on="sheet2">5</col>
            </node>
        </node>
    </node>
</t>

次の点に注意してください。

  1. node両方のトップ要素が属性"a1"の値として持っていると仮定しtitleます。これは簡単に一般化できます。

  2. テンプレート マッチングnodeには、 という名前のパラメーターがあります。これは、他のドキュメントからpOther名前が付けられた対応する要素です。nodeこのテンプレートは、$ が存在する場合にのみ適用されpOtherます。

  3. という名前の対応する要素がnode存在しない場合、別のテンプレートも一致nodeしますが、モードcopyで適用されます。このテンプレートには という名前のパラメーターがpSheetあり、その値はこの要素が属するシート名 (文字列) です。

于 2009-04-01T04:20:28.163 に答える