1

次の XML 構造の XSLT テンプレートを作成しようとしています。

<dealership>
    <division>
        <division_name>BMW</division_name>
        <models>
            <model_no>328i</model_no>       
            <model_no>M3</model_no>
            <model_no>X5</model_no>
            <model_no>528i</model_no>
        </models>
        <salesman>
            <salesman_name>Bob</salesman_name>
            <salesman_name>Jerry</salesman_name>
        </salesman>
        <mechanics>
            <mechanic_name>Greg</mechanic_name>
            <mechanic_name>Mike</mechanic_name>
            <mechanic_name>Sean</mechanic_name>
        </mechanics>
    </division>
</dealership>

次の形式で HTML テーブルに出力する必要があります。

<table>
  <tr>
   <th>Division</th>
   <th>Models</th>
   <th>Salesman</th>
   <th>Mechanics</th>   
 </tr>
 <tr>
  <td>BMW</td>
  <td>328i</td>
  <td>Bob</td>
  <td>Greg</td>
 </tr>
 <tr>
   <td></td>
   <td>M3</td>
   <td>Jerry</td>
   <td>Mike</td>
 </tr>
 <tr>
   <td></td>
   <td>X5</td>
   <td></td>
   <td>Sean</td>
 </tr>
 <tr>
   <td></td>
   <td>528i</td>
   <td></td>
   <td></td>
 </tr>
</table>

問題は、モデル、セールスマン、メカニックの数に制限がないことです。したがって、どういうわけか、テーブルに作成する行の数を知るために、最も多くの子を持つノードを取得する必要があります。次に、行のどのセルが空であるかを追跡する方法が必要です。どんな助けでも大歓迎です。

4

2 に答える 2

0

別の可能な解決策を聞いてください。

<xsl:template match="/dealership/division">

    <xsl:variable name="maxcnt">
        <xsl:for-each select="*" >
            <xsl:sort select="count(*)" order="descending"/>
            <xsl:if test ="position()=1">
                <xsl:value-of select="name(.)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>

    <table>
        <tr>
            <th>Division</th>
            <th>Models</th>
            <th>Salesman</th>
            <th>Mechanics</th>
        </tr>

        <xsl:apply-templates select="*[name()=$maxcnt]/*" mode="row"/>
    </table>
</xsl:template>

<xsl:template match="*" mode="row">
    <xsl:variable name="pos" select="count(preceding-sibling::*)+1"/>
    <tr>
        <td>
            <xsl:value-of select="../../division_name[$pos]"/>
        </td>
        <td>
            <xsl:value-of select="../../models/model_no[$pos]"/>
        </td>
        <td>
            <xsl:value-of select="../../salesman/salesman_name[$pos]"/>
        </td>
        <td>
            <xsl:value-of select="../../mechanics/mechanic_name[$pos]"/>
        </td>
    </tr>
</xsl:template>

最初のステップは、除算のどの子が子の最大数を持っているかを調べることです。これは、子の数でソートされたすべての子に対する for-each によって行われます。したがって、最初は最も多くの子を持つものです。

    <xsl:for-each select="*" >
        <xsl:sort select="count(*)" order="descending"/>
        <xsl:if test ="position()=1">
            <xsl:value-of select="name(.)"/>
        </xsl:if>
    </xsl:for-each>

これは Dimitre Novatchev (*)からの非常に良い説明に基づいています。

于 2013-04-27T10:23:19.823 に答える
0

私が考えることができる最善の方法は、行番号をパラメーターとして名前付きテンプレートを呼び出すことです。テンプレートは、出力するデータがあるかどうかを確認し、ある場合はテーブルのその行を作成し、次の行番号を新しいパラメーター値として使用して自分自身を呼び出します。

このコードは示しています。出力は、指定した XML データに対応していないため、表示される HTML とは異なります。私が知る限り、これは正しいです。

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

  <xsl:template match="/dealership/division">
    <table>
      <tr>
        <th>Division</th>
        <th>Models</th>
        <th>Salesman</th>
        <th>Mechanics</th>   
      </tr>
      <xsl:call-template name="row" >
        <xsl:with-param name="i" select="1" />
      </xsl:call-template>
    </table>
  </xsl:template>

  <xsl:template name="row">
    <xsl:param name="i"/>

    <xsl:if test="models/model_no[$i] |
                  salesman/salesman_name[$i] |
                  mechanics/mechanic_name[$i]">
      <tr>
        <td>
          <xsl:value-of select="division_name[$i]"/>
        </td>
        <td>
          <xsl:value-of select="models/model_no[$i]"/>
        </td>
        <td>
          <xsl:value-of select="salesman/salesman_name[$i]"/>
        </td>
        <td>
          <xsl:value-of select="mechanics/mechanic_name[$i]"/>
        </td>
      </tr>

      <xsl:call-template name="row" >
        <xsl:with-param name="i" select="$i + 1" />
      </xsl:call-template>

    </xsl:if>

  </xsl:template>


</xsl:stylesheet>

出力

<table>
   <tr>
      <th>Division</th>
      <th>Models</th>
      <th>Salesman</th>
      <th>Mechanics</th>
   </tr>
   <tr>
      <td>BMW</td>
      <td>328i</td>
      <td>Bob</td>
      <td>Greg</td>
   </tr>
   <tr>
      <td></td>
      <td>M3</td>
      <td>Jerry</td>
      <td>Mike</td>
   </tr>
   <tr>
      <td></td>
      <td>X5</td>
      <td></td>
      <td>Sean</td>
   </tr>
</table>
于 2013-04-27T06:45:56.097 に答える