質問

は、この質問と似たよう(ただし、新規ユーザーとして、私は唯一のURLを投稿することができ、より多くの関連エントリがあります):

の2つの要素の間にあるのXpathのGet要素

私は「その他/区切り」要素の間で発生する要素のセットの選択について質問があります。にフラットなHTMLテーブルを変換しようとすると、このような状況が発生します XSLTを使用して階層XML構造。私は、テンプレート内の再帰を使用してみましたが、それはデッドロックが生じたようサクソンはこれを受け入れることを拒否し、おそらく私のせいではなく、の冒頭に始めましょう。

まずソースデータは、HTMLのテーブルです:

<table >
    <thead>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
            <th>Column 3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th colspan="3" >Group 1</th>
        </tr>
        <tr>
            <td>attribute 1.1.1</td>
            <td>attribute 1.1.3</td>
            <td>attribute 1.1.2</td>
        </tr>
        <tr>
            <td>attribute 1.2.1</td>
            <td>attribute 1.2.2</td>
            <td>attribute 1.2.3</td>
        </tr>
        <tr>
            <td>attribute 1.3.1</td>
            <td>attribute 1.3.2</td>
            <td>attribute 1.3.3</td>
        </tr>
        <tr>
            <th colspan="3" >Group 2</th>
        </tr>
        <tr>
            <td>attribute 2.1.1</td>
            <td>attribute 2.1.3</td>
            <td>attribute 2.1.2</td>
        </tr>
        <tr>
            <td>attribute 2.2.1</td>
            <td>attribute 2.2.2</td>
            <td>attribute 2.2.3</td>
        </tr>
        <tr>
            <td>attribute 2.3.1</td>
            <td>attribute 2.3.2</td>
            <td>attribute 2.3.3</td>
        </tr>
    </tbody>
</table>

XMLでの目標出力は以下のようになります:

 <groups>
    <group name="Group 1">
        <item attribute1="attribute 1.1.1" attribute2="attribute 1.1.3" attribute3="attribute 1.1.2"/>
        <item attribute1="attribute 1.2.1" attribute2="attribute 1.2.2" attribute3="attribute 1.2.3"/>
        <item attribute1="attribute 1.3.1" attribute2="attribute 1.3.2" attribute3="attribute 1.3.3"/>
    </group>
    <group name="Group 2">
        <item attribute1="attribute 2.1.1" attribute2="attribute 2.1.3" attribute3="attribute 2.1.2"/>
        <item attribute1="attribute 2.2.1" attribute2="attribute 2.2.2" attribute3="attribute 2.2.3"/>
        <item attribute1="attribute 2.3.1" attribute2="attribute 2.3.2" attribute3="attribute 2.3.3"/>
    </group>
</groups>

だから私は、すべての項目のエントリ、(TR要素)を持っており、グループに追加します。これは基本的に私たちが子供のようにTH要素を持つものに遭遇するまで、以下のすべての-兄弟TR要素を選択するためにダウンしています。私はグループの新しい見出しを示し、TH子供を持って、この最初のTRの位置を決めることができれば、これはで行うことができます:

<xsl:for-each select="tbody/tr">
    <xsl:if test="th">
        <xsl:element name="group">
            <xsl:attribute name="name"><xsl:value-of select="th"/></xsl:attribute>
            <xsl:for-each select="following-sibling::tr[position() < $positionOfNextThElement]">            
                <xsl:call-template name="item"/>
            </xsl:for-each>
        </xsl:element>
    </xsl:if>
</xsl:for-each>

しかし、私が最初に遭遇したTR / THタグの位置を決定することはできませんよ。

で述べたように、私は、テンプレート内の再帰で作業しようとした:常に私たちは同様に次の項目でそれを呼び出すようにしたいかどうかを判断する「項目」テンプレートを呼び出し、このテンプレートで。私はこの問題は、テンプレート内からテンプレートの呼び出しであると思います。コンテキスト内の項目が増加していませんか?私たちが取り組んでいるどのような項目を決定するためのパラメータを引き渡すべきでしょうか?

いずれにせよ、これは私が思い付いた何でした

<xsl:for-each select="tbody/tr">
    <xsl:if test="th">
        <xsl:element name="group">
            <xsl:attribute name="name"><xsl:value-of select="th"/></xsl:attribute>
            <xsl:call-template name="item"/>
        </xsl:element>
    </xsl:if>
</xsl:for-each>

<xsl:template name="item">
    <xsl:element name="item">
        <xsl:attribute name="attribute1"><xsl:value-of select="following-sibling::tr[1]/td[1]"/></xsl:attribute>
        <xsl:attribute name="attribute2"><xsl:value-of select="following-sibling::tr[1]/td[2]"/></xsl:attribute>
        <xsl:attribute name="attribute2"><xsl:value-of select="following-sibling::tr[1]/td[3]"/></xsl:attribute>
    </xsl:element>
    <!-- When the next element has not got a TH tag, continue with invoking this template -->
    <xsl:if test="count(following-sibling::tr[1]/th) != 1">
        <xsl:call-template name="item"/>
    </xsl:if>
</xsl:template>

これは歓迎されて実現する方法上の任意の提案!

役に立ちましたか?

解決

変数属性に適合した代替ソリューションは、再帰なしでカウントします。

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="table">
    <groups>
      <xsl:apply-templates select="tbody/tr[th]"/>
    </groups>
  </xsl:template>

  <xsl:template match="tr[th]">
    <group name="{th}">
      <xsl:apply-templates select="
        following-sibling::tr[not(th)][
          generate-id(preceding-sibling::tr[th][1]) = generate-id(current())
        ]
      "/>
    </group>
  </xsl:template>

  <xsl:template match="tr">
    <item>
     <xsl:apply-templates select="td" />
    </item>
  </xsl:template>

  <xsl:template match="td">
    <xsl:attribute name="attribute{position()}">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

他のヒント

コールテンプレート常にコンテキストとして現在のコンテキスト項目を渡します。

テンプレートを呼び出すときに、そのコンテキストは、「アイテム」を増加させない理由は、再帰的にXSがあることです。あなたはおそらく見たように、変換だけで無限再帰に入ります。

あなたは常に正確に3つの属性を生成する必要があると仮定すると、あなたも再帰を必要としません。

これを試してください:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:template match="table">
        <groups>
            <xsl:apply-templates select="tbody/tr[th]"/>
        </groups>
    </xsl:template>

    <xsl:template match="tr[th]">
        <xsl:variable name="id" select="generate-id(.)"/>
        <group name="{string(th)}">
            <xsl:apply-templates
                select="following-sibling::tr[not(th)][generate-id(preceding-sibling::tr[th][1]) = $id]"/>
        </group>
    </xsl:template>

    <xsl:template match="tr">
        <item attribute1="{td[1]}" attribute2="{td[2]}" attribute3="{td[3]}" />                    
    </xsl:template>

</xsl:stylesheet>

これは、各ヘッダー行にテンプレートを適用することによって動作します。これらのテンプレートの各々は、それが最初のヘッダと行の前にいたように、複雑なXPathは、その特定の行を有する任意の次の兄弟行である「その」は、以下の行を呼び出すために使用すること。

もちろん、属性の数が変動した場合は、位置を示すパラメータを渡すことが再帰して増加する必要があります。

あなたがやっていたように、再帰的にそのうちの1つはXSLTのグループ化のための確立された方法がいくつかあります。もう一つの方法は、Muenchianグループと呼ばれています。良い書き込みアップがあるここを。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top