2017-06-29 15 views
2

xsltが新しくxml構造体を使用してテーブルを作成しようとしましたが、各行のフィールド数を制限するのが難しいと感じています。xslt - xslt変換の行数を制限する

<report> 
<status> 
    <statuscheck> 
     <node>node1</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node2</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node3</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node4</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node5</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area1</area> 
    </statuscheck> 
    <statuscheck> 
     <node>node1</node> 
     <RAG>red</RAG> 
     <url>http://www.google.com</url> 
     <area>area2</area> 
    </statuscheck> 
</status> 
<area> 
    <area_name>area1</area_name> 
    <area_name>area2</area_name> 
</area> 

私は、次のXSLTを持っていますが、私はそれがすべての4つの項目の後に新しい行を開始するために得ることができる方法はありますか?実際のXMLには、領域あたり20個のコンポーネントがあります。事前 で

<?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> 
       </style> 
      </head> 

      <body style="font-family: Sky Text;"> 
      <xsl:for-each select="/report/area/area_name"> 
          <div style="font-size: 20px; font-weight: bold; margin: 10px 0 10px 0;"><xsl:value-of select="."/></div> 
          <table style="font-family: Sky Text; border-collapse: collapse; width: 960px;"> 
           <tbody> 
            <xsl:variable name="active_area" select="./text()"></xsl:variable> 
            <xsl:for-each select="/report/status/statuscheck[area/text() = $active_area]"> 
             <td style="width: 240px; border: 1px solid black; text-align: center;" valign="middle"> 
              <xsl:attribute name="class"> 
               <xsl:value-of select="RAG"/> 
              </xsl:attribute> 
              <div style="margin: 10px; font-size: 16px;"> 
              <a> 
               <xsl:attribute name="href"> 
                <xsl:value-of select="url"/> 
               </xsl:attribute> 
               <xsl:value-of select="node"/> 
              </a> 
              </div> 
             </td> 
            </xsl:for-each> 
           </tbody> 
          </table> 
         </xsl:for-each> 
      </body> 
     </html> 
    </xsl:template> 

</xsl:stylesheet> 

おかげギャビン

+0

参照[XSLT 1.0は、異なるノードおよび要素のキーをグループ化](https://stackoverflow.com/q/7061614/ 205233)と非常によく似た質問です。 [関連検索](https://www.google.com/search?q=site%3Astackoverflow.com+xslt+group+by+key)にも同様の質問があります。 – Filburt

+1

本当にこれがテーブルである必要がある理由はありますか?正直なところ、HTMLからは 'statuscheck'ごとにdivブロックを作成し、CSSを使ってそれらをレイアウトするほうがはるかに優れているようです。 – Flynn1179

+0

ありがとう..私はHTMLでかなり新しいですが、CSSのレイアウトをグーグルで調べると、必要なものを実行するようです。ありがとうございます – gav1nb

答えて

1

私は文体の観点から@ Flynn1179さんのコメントに同意に傾いています。厳密にはレイアウト目的ではなく、表形式のデータを表示するためにHTML表を使用する必要があります。データが本質的に表形式のものであれば、それらを列と行にマッピングするのは当然です。しかし、それはXSLTが提示したように仕事をすることができないというわけではありません。

ただし、XSLTがタスクにどのように適用されるかについて説明する前に、まずXSLTが手続き型プログラムのように書かれていることを指摘しておきます。これはXSLTの自然なパラダイムではありません。その中でさえ、XSLTの機能のいくつかを利用して、それをより明瞭かつ簡単にすることはできません。一般的な推奨事項:

  • 代わりにxsl:apply-templatesと別のテンプレートを使用できるxsl:for-eachを使用しないでください。
  • それに加えて、複数のトップレベルテンプレートを使用することを躊躇しないでください。大きなテンプレートを複数の小さなテンプレートに分割することは、長い関数をいくつかの短い関数に分割して、読みやすさ、保守性、および再利用性の点で同じ利点の多くを抱くようなものです。
  • xsl:elementxsl:attributeを使用すると、リテラルの結果要素と属性を使用することをお勧めします。要素/属性名が変換によって計算される必要がある場合を除いて、後者はほとんど必要ありません。
  • 特に、リテラル結果属性の値は「属性値テンプレート」であり、その中でXPath式を計算できることに注意してください。
  • xsl:keykey()について学びます。これらは、新人が考えるよりはるかに有用です。とりわけ、それらはグループ分けに非常に便利です。言ったことで

、そして、あなたのスタイルシートのこのリファクタリングを考えてみます。

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

    <xsl:output method="html"/> 

    <!-- group the statuscheck elements by their areas -->  
    <xsl:key name="area" match="/report/status/statuscheck" use="area"/> 

    <!-- Provides the top-level document structure --> 
    <xsl:template match="/"> 
    <html> 
     <head> 
     <style> 
     </style> 
     </head> 
     <body style="font-family: Sky Text;"> 
     <!-- generate the body contents by transforming the area_name elements --> 
     <xsl:apply-templates select="report/area/area_name"/> 
     </body> 
    </html> 
    </xsl:template> 

    <!-- Transforms area_name elements to produce area information. Note that 
     The template is not restricted to drawing on the subtree rooted at the 
     context node. --> 
    <xsl:template match="area_name"> 
    <xsl:variable name="active_area" select="string(.)"/> 
    <div style="font-size: 20px; font-weight: bold; margin: 10px 0 10px 0;"><xsl:value-of select="$active_area"/></div> 
    <table style="font-family: Sky Text; border-collapse: collapse; width: 960px;"> 
     <tbody> 
     <!-- each row is generated by transforming a distinguished element; 
      specifically, the first --> 
     <xsl:apply-templates select="key('area', $active_area)[position() mod 4 = 1]" mode="row-head"> 
      <!-- this is one way to tell the template we're about to apply which are 
       the other statuscheck element's in the context node's group: --> 
      <xsl:with-param name="area-checks" select="key('area', $active_area)"/> 
     </xsl:apply-templates> 
     </tbody> 
    </table> 
    </xsl:template> 

    <!-- transform a statuscheck node by emitting a <tr> element with a <td> child 
     for each item in the row --> 
    <xsl:template match="statuscheck" mode="row-head"> 
    <xsl:param name="area-checks"/> 
    <xsl:variable name="row-start" select="position() * 4 - 3"/> 
    <tr> 
     <!-- the <td> elements are generated by a separate template --> 
     <xsl:apply-templates select="$area-checks[position() >= $row-start and position() &lt; $row-start + 4]"/> 
    </tr> 
    </xsl:template> 

    <!-- This template and the other matching the same elements are distinguished 
     by their modes. --> 
    <xsl:template match="statuscheck"> 
    <!-- Note how the value of the 'class' literal result attribute is expressed 
     via an XPath expression. You don't need xsl:attribute for that. --> 
    <td class="{RAG}" style="width: 240px; border: 1px solid black; text-align: center;" valign="middle"> 
     <div style="margin: 10px; font-size: 16px;"> 
     <a href="{url}"><xsl:value-of select="node"/></a> 
     </div> 
    </td> 
    </xsl:template> 

</xsl:stylesheet>