2016-03-23 4 views
0

のは、私は以下のリストがあるとしましょう:属性がプログラムによって生成されるとき、特定の属性を持つすべての要素を選択する方法は?

<list> 
    <item>text1</item> 
    <item>text2</item> 
    <item>text3</item> 
    <item type="type1">text4</item> 
    <item type="type1">text5</item> 
    <item type="type1">text6</item> 
    <item>text7</item> 
    <item>text8</item> 
    <item type="type2">text9</item> 
    <item type="type2">text10</item> 
    <item>text11</item> 
    <item>text12</item> 
    <item type="...">...</item> 
    ... 
    <item>...</item> 
    ... 
</list> 

一つの重要なことを、私はtype属性を持つことになりますどのような値が分からないということ!プログラムによって生成されます。 Not this one.私は、いくつかのアイテムが同じ属性を持つことができることを知っています。

そして私はにこのリストを変換したい:「タイプ」属性I出力がちょうど項目内のテキストがない各項目のために、そう

text1 
    text2 
    text3 
    text4, text5, text6 
    text7 
    text8 
    text9, text10 
    text11 
    text12 

。同じ属性を持つアイテムごとに、すべてのアイテムテキストを1行に出力します。どのようにxsltでこれを達成するには?属性がプログラムによって生成されるとき、同じ属性を持つすべてのアイテムを選択する方法は?

答えて

2

タイプによってアイテムをグループ化するとします。

これは、それぞれのタイプをキーとして使用して、タイプを持つすべてのアイテムのインデックスを作成します。

次の次の2つの条件のいずれかに該当する場合にのみ出力行を生成したい:

  • アイテムは何の種類を持っていない、または
  • 項目が
そのタイプの最初のものです

<xsl:if test="not(@type) or generate-id() = generate-id(key('byType', @type)[1])"> 

その型意志出力の最初の項目全てOTHE:のように表すことができる

rsはカンマで区切られています。同じ種類の以下の項目は、(既に印刷されているので)何も出力しないでください。

我々は、我々はこれら2 nodesetsの労働組合として各ライン上に印刷したい項目のリストを定義することができます。

  • (アイテムは何の種類を持っていない場合のために)現在の項目
  • すべて(キーを経由して)現在の項目と同じ型を持っているアイテムのXPathで

これは. | key('byType', @type)ある(nodesetsが二度同じノードが含まれていませんことができます)

ので、この:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" encoding="UTF-8" /> 

    <xsl:key name="byType" match="item[@type]" use="@type" /> 

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

    <xsl:template match="item"> 
     <xsl:if test="not(@type) or generate-id() = generate-id(key('byType', @type)[1])"> 
      <xsl:for-each select=". | key('byType', @type)"> 
       <xsl:value-of select="." /> 
       <xsl:if test="position() &lt; last()">, </xsl:if> 
      </xsl:for-each> 
      <xsl:text>&#xA;</xsl:text> 
     </xsl:if> 
    </xsl:template> 
</xsl:transform> 

出力

 
text1 
text2 
text3 
text4, text5, text6 
text7 
text8 
text9, text10 
text11 
text12 
... 
... 
+0

ありがとうございます!できます! –

1

あなたはMuenchianグループ化を使用します。このような何かが

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

    <xsl:key name="items-by-type" match="item" use="@type" /> 
    <xsl:template match="/list"> 


     <xsl:for-each select="item[count(. | key('items-by-type', @type)[1]) = 1]"> 
      <xsl:if test="not(@type)"> 
       <xsl:value-of select="."/> 
       <xsl:text>&#10;</xsl:text> 
      </xsl:if> 
      <xsl:if test="@type"> 
       <xsl:for-each select="key('items-by-type', @type)"> 
        <xsl:value-of select="." />  
        <xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if> 
       </xsl:for-each>     
       <xsl:text>&#10;</xsl:text> 

      </xsl:if> 
     </xsl:for-each> 


    </xsl:template> 
</xsl:transform> 

http://xsltransform.net/3NJ3914/3

あなたitemのグループにkeyを使用して動作するはずです。@typeが設定されていない場合は、項目を印刷してください。それ以外の場合は、@typeitemをすべて反復して印刷してください。

+0

XSLT 2.0を使用している場合はなぜMuenchianのグループ化で、 'for-each-group'でないのですか? –

+0

投稿にはXSLT 1.0というタグが付けられています。私はXSLTransformのデフォルトバージョンからバージョンを更新するのを忘れていました - それを指摘してくれてありがとう –

+1

XSLT 1.0(http://xsltransform.net/3NJ3914/1) 'xsl:value-of select =" key( 'items- by-type '、@type) "/>'は、グループ内の最初の項目だけを出力します。 –

関連する問題