1

私はXSLTを初めて使用し、今朝のほとんどの時間、このポイントに到達するために遊んでいますが、どのように進めるかがわかりません。

これは、私がやろうとしていることを表すためのテストXMLです。

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="style.xslt"?>
<ResultCollection>
    <ColumnSet>
    <Column>
        <Caption>Site</Caption>
        <DisplayType>String</DisplayType>
    </Column>
    <Column>
        <Caption>Date</Caption>
        <DisplayType>String</DisplayType>
    </Column>
    <Column>
        <Caption>Attendee</Caption>
        <DisplayType>String</DisplayType>
    </Column>
    <Column>
        <Caption>Paid</Caption>
        <DisplayType>Hidden</DisplayType>
    </Column>
    </ColumnSet>
    <RowSet>
        <Row>
            <Site>London</Site>
            <Date>15/06/2012</Date>
            <Attendee>James</Attendee>
            <Paid>Yes</Paid>
        </Row>
        <Row>
            <Site>London</Site>
            <Date>15/06/2012</Date>
            <Attendee>John</Attendee>
            <Paid>Yes</Paid>
        </Row>
</RowSet>
</ResultCollection>

そして、これは私がそれを変換するために使用している関連するXSLTです:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<style type="text/css">
table.resultsCollection
{
    border-collapse:collapse; 
    text-align:center;
    margin:5px; 
    padding:2px;
}

table.resultsCollection tr th,
table.resultsCollection tr td
{
    padding:2px 8px 2px 8px;
}
</style>
</head>
        <body>
        <table border="1" class="resultsCollection">
            <tr bgcolor="#eeeeff">
            <xsl:for-each select="ResultCollection/ColumnSet/Column">
                <xsl:if test="not(self::*/DisplayType[text()]='Hidden')">
                <th><xsl:value-of select="Caption"/></th>
                </xsl:if>
            </xsl:for-each>
            </tr>
            <xsl:for-each select="ResultCollection/RowSet/Row">
                <tr>                
                <td><xsl:value-of select="Site"/></td>
                <td><xsl:value-of select="Date"/></td>
                <td><xsl:value-of select="Attendee"/></td>
                <td><xsl:value-of select="Paid"/></td>
                </tr>
            </xsl:for-each>
        </table>
    </body>
</html>   
</xsl:template>

使用しているXML構造を変更することはできません。変更すると、自分の生活が楽になると思うので、自分で制御することはできません。それでも、私の目標は、読みやすく、つまりXSLTに見えるようにすることです。

問題は、「Column」ノードに、その列を表示するかどうかを決定する「DisplayType」が含まれていることです。'xsl:if'を使用して、そのタイプの列が表示されないようにしました。ただし、これを実行する方法を理解できず、関連するレコードも出力されないようにすることはできません。これら2つを一緒に実行すると、テーブルの4番目の列にヘッダーがないことがわかります。ただし、「有料」ノードのある2つの行の内容は、関係なく出力されます。

2つを同期する方法はありますか?(これが私の最初の刺し傷なので、私が持っているものを証明するための提案も歓迎します)

クリス

4

3 に答える 3

2

まず、for-eachではなくテンプレートルールを使用する習慣を身に付けることをお勧めします。したがって、このコード:

    <xsl:for-each select="ResultCollection/RowSet/Row">
        <tr>                
        <td><xsl:value-of select="Site"/></td>
        <td><xsl:value-of select="Date"/></td>
        <td><xsl:value-of select="Attendee"/></td>
        <td><xsl:value-of select="Paid"/></td>
        </tr>
    </xsl:for-each>

になります

<xsl:apply-templates select="ResultCollection/RowSet/Row" />

プラス

<xsl:template match="Row">
  <tr><xsl:apply-templates/></tr>
</xsl:template>

<xsl:template match="Row/*">
  <td><xsl:value-of select="."/></td>
</xsl:template>

これで、必要な変更がRowの子、つまり最後のテンプレートルールに影響します。これに変更します:

<xsl:template match="Row/*">
  <xsl:variable name="position" select="position()"/>
  <xsl:if test="not(ancestor::ResultCollection/ColumnSet/Column[$position]/DisplayType='Hidden')">
    <td><xsl:value-of select="."/></td>
  </xsl:if>
</xsl:template>
于 2012-05-28T17:35:20.543 に答える
1

あなたは鍵を作りたいかもしれません

<xsl:key name="VisibleCols" match="ResultCollection/ColumnSet/Column[DisplayType!='Hidden']" use="Caption"/>

のように使用します

<xsl:for-each select="ResultCollection/ColumnSet/Column[DisplayType!='Hidden']">
    <th><xsl:value-of select="Caption"/></th>
</xsl:for-each>
</tr>
<xsl:for-each select="ResultCollection/RowSet/Row">
    <tr>
    <xsl:for-each select="*[key('VisibleCols', name())]">
        <td><xsl:value-of select="."/></td>
    </xsl:for-each>
    </tr>
</xsl:for-each>

事前定義された要素のセットを使用しませんが、ソースxmlにあるものをすべて取得することに注意してください。これは、必要なものではない可能性があります。また、(他の回答とは対照的に)xmlファイル内の位置ではなく、列名でセルをヘッダーにリンクします。

追加:また、変数を使用して列を保持することができます:

<xsl:variable name="VisibleCols" select="ResultCollection/ColumnSet/Column[DisplayType!='Hidden']"/>
<xsl:for-each select="$VisibleCols">
    <th><xsl:value-of select="Caption"/></th>
</xsl:for-each>
</tr>
<xsl:for-each select="ResultCollection/RowSet/Row">
    <tr>
    <xsl:for-each select="*">
        <xsl:if test="$VisibleCols[Caption=name(current())]">
        <td><xsl:value-of select="."/></td>
        </xsl:if>
    </xsl:for-each>
    </tr>
</xsl:for-each>
于 2012-05-28T17:29:02.917 に答える
1

このスタイルシートは正しい結果を生成するはずです:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
      <head>
        <style type="text/css">
          table.resultsCollection
          {
          border-collapse:collapse;
          text-align:center;
          margin:5px;
          padding:2px;
          }

          table.resultsCollection tr th,
          table.resultsCollection tr td
          {
          padding:2px 8px 2px 8px;
          }
        </style>
      </head>
      <body>
        <table border="1" class="resultsCollection">
          <xsl:variable name="columns" select="ResultCollection/ColumnSet/Column"/>
          <tr bgcolor="#eeeeff">
            <xsl:for-each select="$columns">
              <xsl:if test="DisplayType!='Hidden'">
                <th>
                  <xsl:value-of select="Caption"/>
                </th>
              </xsl:if>
            </xsl:for-each>
          </tr>
          <xsl:for-each select="ResultCollection/RowSet/Row">
            <tr>
              <xsl:for-each select="*">
                <xsl:variable name="pos" select="position()"/>
                <xsl:if test="$columns[$pos]/DisplayType!='Hidden'">
                  <td>
                    <xsl:value-of select="."/>
                  </td>
                </xsl:if>
              </xsl:for-each>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

列のリストを変数に保存します。この変数は、行を処理するときにアクセスされ、列を表示する必要があるかどうかを確認します。

のテストDisplayTypeは例示されています-[text()]部品は必要ありません。

于 2012-05-28T17:40:02.130 に答える