4

このXMLを考えると

<Xml>
    <Thing id="1"  >
        <Foo id="11" parentId="12"/>
        <Foo id="12"/>
    </Thing>
    <Thing id="2" parentId="1" />
    <Thing id="3" parentId="2" />
    <Thing id="4">
        <Foo id="11" parentId="15"/>
        <Foo id="12" parentId="14"/>
        <Foo id="13" parentId="11"/>
        <Foo id="14" parentId="15"/>
        <Foo id="15"/>      
    </Thing>
</Xml>

兄弟のすべてのコレクションを取得し、それらを独自の階層に組み立てたいと思います。

parentId値を持つすべての「Thing」ノードは、対応するThingノードの下にネストする必要があります。parentId値を持つすべての「Foo」ノードは、対応するFooノードの下にネストする必要がありますが、その兄弟内にのみネストする必要があります。この例には、2セットのFoo兄弟があります。

私はこれを作成しようとしています:

<Xml>
    <Thing id="1" >
        <Foo id="12">
            <Foo id="11" parentId="12"/>
        </Foo>        
        <Thing id="2" parentId="1" >
            <Thing id="3" parentId="2" />
        </Thing>
    </Thing>            
    <Thing id="4" >
        <Foo id="14" parentId="12">
            <Foo id="12" parentId="14"/>
        </Foo>
        <Foo id="15">
            <Foo id="11" parentId="15">
                <Foo id="13" parentId="11"/>
            </Foo>
        </Foo>
    </Thing>
</Xml>

この例は近づいています: XSLT 1.0を使用して非階層XMLファイルに構造を追加するにはどうすればよいですか?

IDテンプレートを使用して、すべてのノードと属性を保持しました。次に、兄弟の@parentId値が私の@id値と等しくなるように、兄弟(後続または先行)を持つすべてのノードでオーバーライドするテンプレートを一致させたいと思います。私が最も近づいたのは、一致するid/parentId値をハードコーディングすることでした。

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

    <xsl:output indent="yes"/>

    <!-- override identity rule with template to match on
        a node who has siblings, where sibling/@parentId == ./@id
    -->
    <xsl:template match="node()[@id='1' and (preceding-sibling::*[@parentId = 1] or following-sibling::*[@parentId = 1])]">
       <captured>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
       </captured>
    </xsl:template>  


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


</xsl:stylesheet>

parentId値に基づいてXpathマッチング兄弟の述語で使用する現在のノードの@id値を取得する方法がわかりません。

次に、現在のノードの兄弟をその下にネストします。兄弟の@ParentIdは私の@idと同じです。

4

1 に答える 1

4

まず第一に、提供されたXMLドキュメントのエラーに注意してください

    <Foo id="12" parentId="14"/>
    <Foo id="13" parentId="11"/>
    <Foo id="14" parentId="12"/>

with12とFoowithの間には循環関係があります。これはサイクルを作り、「階層」ではありません。また、これら2つの要素は、階層の最上位からは到達できません。訂正してくださいidFoo14Foo

この変換

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kElemById" match="*"
   use="concat(generate-id(..), '+', @id)"/>
 <xsl:key match="*" name="kDescendants"
  use="concat(generate-id(key('kElemById', 
                              concat(generate-id(..), '+',@parentId))),
             '+', @parentId)"/>

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

 <xsl:template match="/*">
  <Xml>
   <xsl:apply-templates select="*[not(@parentId)]"/>
  </Xml>
 </xsl:template>

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

    <xsl:apply-templates select="*[not(@parentId)]"/>

    <xsl:apply-templates select=
       "key('kDescendants', concat(generate-id(), '+',  @id))"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

提供されたXMLドキュメントに適用した場合

<Xml>
    <Thing id="1"  >
        <Foo id="11" parentId="12"/>
        <Foo id="12"/>
    </Thing>
    <Thing id="2" parentId="1" />
    <Thing id="3" parentId="2" />
    <Thing id="4">
        <Foo id="11" parentId="15"/>
        <Foo id="12" parentId="14"/>
        <Foo id="13" parentId="11"/>
        <Foo id="14" parentId="12"/>
        <Foo id="15"/>
    </Thing>
</Xml>

到達不能な要素を除いて、正しい結果を生成します

<Xml>
   <Thing id="1">
      <Foo id="12">
         <Foo id="11" parentId="12"/>
      </Foo>
      <Thing id="2" parentId="1">
         <Thing id="3" parentId="2"/>
      </Thing>
   </Thing>
   <Thing id="4">
      <Foo id="15">
         <Foo id="11" parentId="15">
            <Foo id="13" parentId="11"/>
         </Foo>
      </Foo>
   </Thing>
</Xml>
于 2012-05-26T01:58:35.043 に答える