2017-05-15 5 views
0

変数内のノードをフィルタリング/グループ化しようとしています。XSLT:変数のフィルタ/グループノード

XML:

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

    <xsl:template match="row"> 
     <xsl:element name="row"> 
      <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="cell"> 
     <xsl:variable name="attribute" select="@n"/> 
     <xsl:variable name="sequence"> 
      <xsl:call-template name="seq"> 
       <xsl:with-param name="attribute" select="$attribute"/> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:for-each-group select="$sequence" group-by="cell/@val"> 
      <xsl:sequence select="."></xsl:sequence> 
     </xsl:for-each-group> 
    </xsl:template> 

    <xsl:template name="seq"> 
     <xsl:param name="attribute"/> 
     <xsl:element name="cell"> 
      <xsl:attribute name="val"> 
       <xsl:value-of select="$attribute"/> 
      </xsl:attribute> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

意図した出力:

<?xml version="1.0" encoding="UTF-8"?> 
<row> 
    <cell val="1"/> 
    <cell val="2"/> 
    <cell val="3"/> 
    <cell val="4"/> 
    <cell val="5"/> 
</row> 

XML-コードがはるかに複雑なファイルのための単なる一例である2

<?xml version="1.0" encoding="UTF-8"?> 
<row> 
    <cell n="1"/> 
    <cell n="2"/> 
    <cell n="3"/> 
    <cell n="4"/> 
    <cell n="2"/> 
    <cell n="5"/> 
</row> 

XSLT。私がしたいことは、すべての要素cellを最初に処理し、その結果を変数に保存することです。 2回目の実行では、シーケンスのノードをフィルタリングまたは再グループ化します。

Iはまた、述語と$sequenceをフィルタリングすることを試みた:

<xsl:sequence select="$sequence/*[@val != preceding-sibling::cell/@val]"/> 

この場合、出力ファイルが空です。

EDIT 2(今それが動作する):ここ

<?xml version="1.0" encoding="UTF-8"?> 

<xsl:template match="row"> 
    <xsl:variable name="sequence"> 
     <xsl:for-each select="cell"> 
      <xsl:variable name="attribute" select="@n"/> 
      <xsl:call-template name="seq"> 
       <xsl:with-param name="attribute" select="$attribute"/> 
      </xsl:call-template> 
     </xsl:for-each> 
    </xsl:variable> 
    <row> 
     <xsl:for-each-group group-by="@val" select="$sequence/*"> 
      <xsl:sequence select="."/> 
     </xsl:for-each-group> 
    </row> 
</xsl:template> 

<xsl:template name="seq"> 
    <xsl:param name="attribute"/> 
    <xsl:element name="cell"> 
     <xsl:attribute name="val"> 
      <xsl:value-of select="$attribute"/> 
     </xsl:attribute> 
    </xsl:element> 
</xsl:template> 

+1

です。すべての 'cell'要素を最初に処理し、結果を変数に格納して処理したい場合は、' row'(またはそれ以上)のコンテキストから行う必要があります。私はそれがこの時点で言えることすべてについてだと思う。 –

+0

私は以前のコードを編集しようとしましたが、今は '$属性 'を渡すことができません。私はXSLTについての私の知識がここに限界を感じるのではないかと心配しています。 – Ferestes

+0

Ditto Michaelのコメント - あなたがしようとしていることははっきりしていません。また、 '$ sequence'変数には単一の' cell'要素、 ' '。 '$ sequence'は一つの要素しか持っていないので、' preceding-sibling'を使って '$ sequence'をフィルタリングしようとすると失敗します。 Michaelが言っているように、一度に複数の「セル」をターゲットにするには、 'row'以上のコンテキストから開始する必要があります。 –

答えて

1

はによって<cell n="x">...</cell><cell val="n">...</cell>に第1およびグループこれらの細胞要素を変換するXSLT 2.0スタイルシートでありますval重複を排除する属性:

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

    <xsl:output indent="yes"/> 

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

    <xsl:template match="row"> 
     <xsl:copy> 
      <xsl:variable name="transformed-cells"> 
       <xsl:apply-templates select="cell"/> 
      </xsl:variable> 
      <xsl:for-each-group select="$transformed-cells/cell" group-by="@val"> 
       <xsl:copy-of select="."/> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="cell/@n"> 
     <xsl:attribute name="val" select="."/> 
    </xsl:template> 

</xsl:transform> 

出力はあなたの例では、全く明らかではない

<row> 
    <cell val="1"/> 
    <cell val="2"/> 
    <cell val="3"/> 
    <cell val="4"/> 
    <cell val="5"/> 
</row> 

http://xsltransform.net/a9Giwz

+0

ありがとう!私の例はそれほど良いものではなかったと私は思います。これは目的の出力ではなく、出力を達成するために、呼び出されたテンプレートの結果を保存する変数を使用します。 – Ferestes

+1

'xsl:variable 'の内部で' xsl:call-template'をあなたが理解できない理由でやりたがっているように思われる)または 'xsl:apply-templates'(この例ではXSLTでノードを処理する通常の方法で行ったように)変数の使用を変更しません私の答えに示されている 'xsl:for-each-group'にあります。その答えは、変数の内容をどのように処理するかを示すのに役立ちます。 –

+0

私が 'xsl:call-template'を参照するためには' xsl:call-template'を使います。とにかく、あなたは正しいです。私は間違った方法で 'xsl:for-each-group'を使いました。今それはすべて正常に動作します。ありがとう。 – Ferestes