2011-06-20 10 views
4

フラットXMLドキュメントからネストされたXMLドキュメントを作成しようとしています。ここで、ネット上で利用可能な他のリソースを検索した後、muenchainメソッドが解決策になるかもしれないと思われますが、私は自分の状況にそれを適用するのに苦労しています。XLSTでmuenchianメソッドを使用してネストされたXMLを生成する

私は翻訳する必要がXMLの形式は次のとおりです。

<i> 
    <item id="1" name="one" sub_id="10" sub_name="s1" detail_id="t1" detail_name="aaaa"/> 
    <item id="1" name="one" sub_id="10" sub_name="s1" detail_id="t2" detail_name="bbb"/> 
    <item id="1" name="one" sub_id="20" sub_name="s2" detail_id="t1" detail_name="ccc"/> 
    <item id="1" name="one" sub_id="20" sub_name="s2" detail_id="t2" detail_name="ddd"/> 
    <item id="2" name="two" sub_id="10" sub_name="s1" detail_id="t1" detail_name="eee"/> 
    <item id="2" name="two" sub_id="10" sub_name="s1" detail_id="t2" detail_name="fff"/> 
    <item id="2" name="two" sub_id="20" sub_name="s2" detail_id="t1" detail_name="ggg"/> 
    <item id="2" name="two" sub_id="20" sub_name="s2" detail_id="t2" detail_name="hhh"/> 
    <item id="3" name="three" /> 
    <item id="4" name="four" sub_id="10" sub_name="s1" detail_id="t1" detail_name="mmm"/> 
    <item id="4" name="four" sub_id="10" sub_name="s1" detail_id="t2" detail_name="nnn"/> 
    <item id="4" name="four" sub_id="20" sub_name="s2" detail_id="t1" detail_name="ooo"/> 
    <item id="4" name="four" sub_id="20" sub_name="s2" detail_id="t2" detail_name="ppp"/> 
</i> 

私は、次の形式でXMLにこれをtranformしたいと思います:

<i> 
    <item id="1" name="one" sub_items="true"> 
     <sub_item sub_id="10" sub_name="s1"> 
     <detail detail_id="t1" detail_name="aaaa"/> 
     <detail detail_id="t2" detail_name="bbb"/> 
     </sub_item> 
     <sub_item sub_id="20" sub_name="s2"> 
     <detail detail_id="t1" detail_name="ccc"/> 
     <detail detail_id="t2" detail_name="ddd"/> 
     </sub_item> 
    </item> 
    <item id="2" name="two" sub_items="true"> 
     <sub_item sub_id="10" sub_name="s1"> 
     <detail detail_id="t1" detail_name="eee"/> 
     <detail detail_id="t2" detail_name="fff"/> 
     </sub_item> 
     <sub_item sub_id="20" sub_name="s2"> 
     <detail detail_id="t1" detail_name="ggg"/> 
     <detail detail_id="t2" detail_name="hhh"/> 
     </sub_item> 
    </item> 
    <item id="3" name="three" sub_items="false"/> 
    <item id="4" name="four" sub_items="true"> 
     <sub_item sub_id="10" sub_name="s1"> 
     <detail detail_id="t1" detail_name="mmm"/> 
     <detail detail_id="t2" detail_name="nnn"/> 
     </sub_item> 
     <sub_item sub_id="20" sub_name="s2"> 
     <detail detail_id="t1" detail_name="ooo"/> 
     <detail detail_id="t2" detail_name="ppp"/> 
     </sub_item> 
    </item> 
    </i> 

私の研究から、私は次のXLSTを持っています変換を実行します。 item id属性のkeyメソッドを使用します。これは、各レベルで指定されたアイテムIDのすべてを繰り返すデータを正しくグループ化するわけではありません。だから私の問題は、どのように私は別のキーステートメントを使用する必要がある各ネストレベルを出力するために必要なノードを選択するに行くのですか?

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="indexes" match="i/item" use="@id"/> 
    <xsl:template match="i"> 
    <i> 
    <xsl:for-each select="item[count(. | key('indexes',@id)[1]) = 1]" > 
     <xsl:sort select="@id"/> 
     <item> 
     <xsl:attribute name="id"> 
      <xsl:value-of select="@id"/> 
     </xsl:attribute> 
     <xsl:attribute name="name"> 
      <xsl:value-of select="@name"/> 
     </xsl:attribute> 
     <xsl:attribute name="hasRows"> 
      <xsl:value-of select="@id"/> 
     </xsl:attribute> 
     <xsl:for-each select="key('indexes',@id)"> 
      <subitem> 
      <xsl:attribute name ="sub_id"> 
       <xsl:value-of select="@sub_id"/> 
      </xsl:attribute> 
      <xsl:attribute name ="sub_name"> 
       <xsl:value-of select="@sub_name"/> 
      </xsl:attribute> 
      <xsl:for-each select="key('indexes',@id)"> 
       <segment> 
       <xsl:attribute name ="detail_id"> 
        <xsl:value-of select="@detail_id"/> 
       </xsl:attribute> 
       <xsl:attribute name ="detail_name"> 
        <xsl:value-of select="@detail_name"/> 
       </xsl:attribute> 
       </segment> 
      </xsl:for-each> 
      </subitem> 
     </xsl:for-each> 
     </item> 
    </xsl:for-each> 
    </i> 
    </xsl:template> 
</xsl:stylesheet> 

また、それはそうではないときの項目のサブ項目/詳細が存在し、ときで* sub_items *属性を移入することは可能でしょうか?

最後に、XSLTの理解とスキルを向上させるために、誰もが良い学習リソースを推薦できますか?

+0

をあなたがここに少しの努力を必要とし、複数のレベルでのグループ化のmeunchanメソッドを使用します。あなたはこの例からインスピレーションを得ようとすることができます(http://stackoverflow.com/questions/6346740/xsl-to-create-folders-based-on-attribute/6349141#6349141)、またはインターネットで " xslt meunhcan "またはここで熱狂的な回答者の誰かを待つ。 –

+0

+1本当に良い質問。 –

+0

AVTとテンプレートモードで人生を簡単にする方法について私の答えを見てください。 –

答えて

1

お知らせこのXSLT 1.0を使用して変換:グループ最初のレベルの項目に使用される属性の定義)

  • つのメインキーを、簡素化する

    • AVT(属性値テンプレート)
    • サブレベルのグループ化を実行するための1秒の複合キー
    • xsl:apply-templatesモードの広範な使用、対xsl:for-each

      <xsl:stylesheet version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
      
      <xsl:output method="xml" indent="yes"/> 
      <xsl:strip-space elements="*"/> 
      
      <xsl:key name="kSubs" match="item" use="concat(@id,'|',@sub_id)"/> 
      <xsl:key name="kItems" match="item" use="@id"/> 
      
      <xsl:template match="i"> 
          <i> 
           <xsl:apply-templates select="item[ 
            generate-id() 
             = generate-id(key('kItems',@id)[1])]"/> 
          </i> 
      </xsl:template> 
      
      <xsl:template match="item"> 
          <item id="{@id}" name="{@name}" sub_items="{boolean(@sub_id)}"> 
           <xsl:apply-templates select=".|following-sibling::item[ 
            (generate-id() 
              = generate-id(key('kSubs',concat(@id,'|',@sub_id))[1])) 
            and 
            (./@id 
              = current()/@id) 
            ]" mode="sub_id"/> 
          </item> 
      </xsl:template> 
      
      <xsl:template match="item[@sub_id]" mode="sub_id"> 
          <sub_item sub_id="{@sub_id}" sub_name="{@sub_name}"> 
           <xsl:apply-templates select="key('kSubs',concat(@id,'|',@sub_id))" 
           mode="detail"/> 
          </sub_item> 
      </xsl:template> 
      
      <xsl:template match="item" mode="detail"> 
          <detail detail_id="{@detail_id}" detail_name="{@detail_name}"/> 
      </xsl:template> 
      
      </xsl:stylesheet> 
      

    応用あなたの質問に示す入力で、生産:

    <i> 
        <item id="1" name="one" sub_items="true"> 
         <sub_item sub_id="10" sub_name="s1"> 
         <detail detail_id="t1" detail_name="aaaa"/> 
         <detail detail_id="t2" detail_name="bbb"/> 
         </sub_item> 
         <sub_item sub_id="20" sub_name="s2"> 
         <detail detail_id="t1" detail_name="ccc"/> 
         <detail detail_id="t2" detail_name="ddd"/> 
         </sub_item> 
        </item> 
        <item id="2" name="two" sub_items="true"> 
         <sub_item sub_id="10" sub_name="s1"> 
         <detail detail_id="t1" detail_name="eee"/> 
         <detail detail_id="t2" detail_name="fff"/> 
         </sub_item> 
         <sub_item sub_id="20" sub_name="s2"> 
         <detail detail_id="t1" detail_name="ggg"/> 
         <detail detail_id="t2" detail_name="hhh"/> 
         </sub_item> 
        </item> 
        <item id="3" name="three" sub_items="false"/> 
        <item id="4" name="four" sub_items="true"> 
         <sub_item sub_id="10" sub_name="s1"> 
         <detail detail_id="t1" detail_name="mmm"/> 
         <detail detail_id="t2" detail_name="nnn"/> 
         </sub_item> 
         <sub_item sub_id="20" sub_name="s2"> 
         <detail detail_id="t1" detail_name="ooo"/> 
         <detail detail_id="t2" detail_name="ppp"/> 
         </sub_item> 
        </item> 
    </i> 
    
  • +1

    @empoと@Erlockの両方のおかげでテンプレートパターンの回答が優先されていたので、どちらの回答も受け入れられました。 – MPD

    2

    ネクストグループ化の場合、Muenchianメソッドはトリッキーです。グループ化の最初のレベルは簡単に管理できますが、他のグループでは以前のIDで構成された複合キーを使用して要素をインデックス化する必要があります。

    <?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
        <xsl:output indent="yes" /> 
        <xsl:key name="items" match="item" use="@id" /> 
        <xsl:key name="sub-items" match="item" use="concat(@id, '|', @sub_id)" /> 
        <xsl:template match="i"> 
         <i> 
         <xsl:for-each select="item[generate-id() = generate-id(key('items', @id)[1])]"> 
          <xsl:copy> 
          <xsl:copy-of select="@id|@name" /> 
          <xsl:choose> 
          <xsl:when test="count(key('items', @id)) &gt; 1"> 
          <xsl:attribute name="sub_items">true</xsl:attribute> 
          <xsl:for-each select="key('items', @id)[generate-id() = generate-id(key('sub-items', concat(@id, '|', @sub_id))[1])]"> 
          <sub_item> 
          <xsl:copy-of select="@sub_id|@sub_name" /> 
          <xsl:for-each select="key('sub-items', concat(@id, '|', @sub_id))"> 
           <detail> 
           <xsl:copy-of select="@detail_id|@detail_name" /> 
           </detail> 
          </xsl:for-each> 
          </sub_item> 
          </xsl:for-each> 
         </xsl:when> 
          <xsl:otherwise> 
          <xsl:attribute name="sub_items">false</xsl:attribute> 
          </xsl:otherwise> 
         </xsl:choose> 
          </xsl:copy> 
         </xsl:for-each> 
         </i> 
        </xsl:template> 
    </xsl:stylesheet> 
    
    +0

    答えに感謝しましたが、テンプレートの回答の構造が好まれましたが、おかげさまで大変感謝しています。 – MPD

    関連する問題