1

次の形式の XML ファイルがあります。

 <DataSet>
  <Data id ="1" columns ="4">
    <item name ="data1" value="value1"/>
    <item name ="data2" value="value2"/>
    <item name ="data3" value="value3"/>
    <item name ="data4" value="value4"/>
    <item name ="data5" value="value5"/>
  </Data>
  <Data id="2" columns ="2">
    <item name ="data1" value="value1"/>
    <item name ="data2" value="value2"/>
    <item name ="data3" value="value3"/>
    <item name ="data4" value="value4"/>
  </Data>
</DataSet>

次のテーブル構造を取得するには、XSL 変換が必要です。ここでのアイデアは、隣接する 2 つのセルに name 属性と value 属性を表示することです。したがって、「項目」は 2 つの列に関連付けられ、行には 2 つの項目の名前と値のペアが保持されます。列数は Data 要素で指定され、常に 2 の倍数になります。

<report>
  <table>
    <tr>
      <td>data1</td>
      <td>value1</td>
      <td>data2</td>
      <td>value2</td>
    </tr>
    <tr>
      <td>data3</td>
      <td>value3</td>
      <td>data4</td>
      <td>value4</td>
    </tr>
    <tr>
      <td>data5</td>
      <td>value5</td>
      <td></td>
      <td></td>
    </tr>
 </table>
 <table>
    <tr>
      <td>data1</td>
      <td>value1</td>
    </tr>
    <tr>
      <td>data2</td>
      <td>value2</td>
    </tr>
    <tr>
      <td>data3</td>
      <td>value3</td>
    </tr>
    <tr>
      <td>data4</td>
      <td>value4</td>
    </tr>
  </table>
</report>
4

3 に答える 3

1

これははるかに簡単な解決策です。

この XSLT 1.0 スタイルシート...

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

<xsl:template match="/*">
  <report>
    <xsl:apply-templates />
  </report>
</xsl:template>

<xsl:template match="Data">
  <xsl:variable name="cols" select="@columns" />
  <table>
    <xsl:for-each select="item[position()*2 mod $cols = (2 mod $cols)]">
      <tr>
       <xsl:for-each select="(.|following-sibling::item)
          [ position()*2 &lt;= $cols]">
         <td><xsl:value-of select="@name" /></td>  
         <td><xsl:value-of select="@value" /></td>  
       </xsl:for-each> 
       <xsl:if test="position()=last()">
         <xsl:for-each select="((/)//*)[position() &lt;=
              ($cols - (count(.|following-sibling::item)*2))]">
            <td />
         </xsl:for-each>   
       </xsl:if>  
      </tr>  
    </xsl:for-each>  
  </table>
</xsl:template>

</xsl:stylesheet>

...この入力に適用すると...

<DataSet>
  <Data id ="1" columns ="4">
    <item name ="data1" value="value1"/>
    <item name ="data2" value="value2"/>
    <item name ="data3" value="value3"/>
    <item name ="data4" value="value4"/>
    <item name ="data5" value="value5"/>
  </Data>
  <Data id="2" columns ="2">
    <item name ="data1" value="value1"/>
    <item name ="data2" value="value2"/>
    <item name ="data3" value="value3"/>
    <item name ="data4" value="value4"/>
  </Data>
</DataSet>   

...収量...

<report>
  <table>
    <tr>
      <td>data1</td>
      <td>value1</td>
      <td>data2</td>
      <td>value2</td>
    </tr>
    <tr>
      <td>data3</td>
      <td>value3</td>
      <td>data4</td>
      <td>value4</td>
    </tr>
    <tr>
      <td>data5</td>
      <td>value5</td>
      <td></td>
      <td></td>
    </tr>
  </table>
  <table>
    <tr>
      <td>data1</td>
      <td>value1</td>
    </tr>
    <tr>
      <td>data2</td>
      <td>value2</td>
    </tr>
    <tr>
      <td>data3</td>
      <td>value3</td>
    </tr>
    <tr>
      <td>data4</td>
      <td>value4</td>
    </tr>
  </table>
</report>

説明

  1. position()出力をマトリックスに構造化するために非常に簡単に使用できます。これは、多くのパラメーターを持つ複雑な呼び出しテンプレートよりもはるかに適しています。
  2. htmlデフォルトの出力方法の代わりに出力方法を使用しますxml。これにより、空の要素のエンコーディングの html スタイルが得られます ( <td></td>over xml styleなど</td>)。
  3. Piez メソッドを使用して、テーブルの最後の行に奇数の空のテーブル セルを出力します。
于 2012-10-14T13:36:53.713 に答える
1

提供された入力に適用される次の XSL 変換により、目的の出力が生成されます。いくつかの説明を以下に示します。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/DataSet"><report>
        <xsl:apply-templates select="@*|node()" />
    </report></xsl:template>

    <xsl:template match="Data">
        <xsl:variable name="count" select="count(item)" />
        <xsl:variable name="M" select="@columns div 2" />
        <xsl:variable name="N" select="($count + ($count mod $M)) div $M" />
        <table>
            <xsl:call-template name="nth-row">
                <xsl:with-param name="n" select="1" />
                <xsl:with-param name="M" select="$M" />
                <xsl:with-param name="N" select="$N" />
            </xsl:call-template>
        </table>
    </xsl:template>

    <xsl:template name="nth-row">
        <xsl:param name="n" />
        <xsl:param name="N" />
        <xsl:param name="M" />
        <tr>
            <xsl:call-template name="nmth-cell">
                <xsl:with-param name="n" select="$n" />
                <xsl:with-param name="m" select="1" />
                <xsl:with-param name="N" select="$N" />
                <xsl:with-param name="M" select="$M" />
            </xsl:call-template>
        </tr>
        <xsl:if test="$N > $n">
            <xsl:call-template name="nth-row">
                <xsl:with-param name="n" select="$n + 1" />
                <xsl:with-param name="N" select="$N" />
                <xsl:with-param name="M" select="$M" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template name="nmth-cell">
        <xsl:param name="n" />
        <xsl:param name="m" />
        <xsl:param name="N" />
        <xsl:param name="M" />
        <xsl:variable name="pos" select="($n - 1) * $M + $m" />
        <xsl:choose>
            <xsl:when test="item[position()=$pos]">
                <td><xsl:value-of select="item[position()=$pos]/@name" /></td>
                <td><xsl:value-of select="item[position()=$pos]/@value" /></td>
            </xsl:when>
            <xsl:otherwise>
                <td></td>
                <td></td>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:if test="$M > $m">
            <xsl:call-template name="nmth-cell">
                <xsl:with-param name="n" select="$n" />
                <xsl:with-param name="m" select="$m + 1" />
                <xsl:with-param name="N" select="$N" />
                <xsl:with-param name="M" select="$M" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:transform>
  1. マッチング/DataSetによりルート要素が生成され、<report />テンプレートの適用が続行されます。

  2. Data内部からのマッチングはfor each要素を/DataSet生成し、という名前のテンプレートを呼び出して興味深い部分を開始します。使用される変数とパラメーターは次のとおりです。<table /><Data />nth-row

    • n : 1 から始まる現在の行の番号
    • M@columns : 属性を 2 で割った値から計算された列の数 (それぞれ<item />が 2 つの<td />要素になるため)。
    • N : 行数。存在する要素の数をM<item />で割った値から計算されます。整数値の切り捨てを考慮して、剰余が前に追加されます。div$count mod $M$count
  3. ここで、再帰的なテンプレート呼び出しがいくつかあります。が呼び出されるたびnth-rowに a を出力し、適切なパラメーターを使用して<tr />呼び出します。nmth-cell現在の行が最後の行ではない限り、nth-rowの増分値で再帰的に呼び出されます$n

  4. 最後に、テンプレートnmth-cellは呼び出されるたびに<td />、適切な からの値を含む 2 つの要素を出力する<item />か、対応する がない場合は何も出力しません<item />。現在の列が最後の列でない限り、nmth-cellの増分値で再帰的に呼び出されます$m

これが役立つことを願っています。これに問題があるか、不明な点がある場合は、お気軽にお尋ねください。

于 2012-10-12T20:00:53.350 に答える
0

私はあなたが望むフォーマットを正確には知りませんが、これはあなたを近づけるはずです。データと値のペアを並べて、データセットごとにテーブルを作成します。書式設定のヘルプも必要な場合はコメントしてください

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
  <report>
      <xsl:for-each select="DataSet/Data">
      <table>
          <xsl:for-each select="item">
              <tr>
                  <td><xsl:value-of select="@name"/></td>
                  <td><xsl:value-of select="@value"/></td>
              </tr>
          </xsl:for-each>
       </table>
       </xsl:for-each>
  </report>
  </body>
  </html>
</xsl:template>

于 2012-10-12T20:02:41.767 に答える