1

だから私はこのXMLを持っています:

<Main>
 <TB>
    --> some elements - not relevant
   <Area>
     <Type>A</Type>
     <Street>
       <Position>5</Position>
       <House>

       --> some elements

       </House>
     </Street>
     <Street>
       <Position>5</Position>
       <Block>

       --> some elements

       </Block>
     </Street>
     <Street>
       <Position>6</Position>
       <House>

       --> some elements

       </House>
     </Street>
     <Street>
       <Position>6</Position>
       <Block>

       --> some elements

       </Block>
     </Street>
   </Area>
   <Area>
    <Type>B</Type>
   --> same structure but with several repetitions of Position 7 and 8.

   </Area>
 </TB>
</Main>

そして、私はそれを次のように注文したい:

<Area>
   <Type>A</Type>
     <Street>
       <Position>5</Position>
       <House>

       --> some elements

       </House>
       <Block>

       --> some elements

       </Block>
     </Street>
     <Street>
       <Position>6</Position>
       <House>

       --> some elements

       </House>
       <Block>

       --> some elements

       </Block>
     </Street>
   </Area>
   <Area>
     <Type>B</Type>
   --> same structure for Position 7 and 8.

   </Area>

そして、この XSLT を使用して変換しています。

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

  <xsl:key name="streetByPosition" match="Street" use="Position" />

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

  <!-- for the first Street in each Position -->
  <xsl:template match="Street[generate-id() =
                            generate-id(key('streetByPosition', Position)[1])]">
    <Street>
      <!-- copy in the Position element once only -->
      <xsl:apply-templates select="Position" />
      <!-- copy in all sub-elements except Position from all matching Streets-->
      <xsl:apply-templates select="
            key('streetByPosition', Position)/*[not(self::Position)]" />
    </Street>
  </xsl:template>

  <!-- ignore all other Street elements -->
  <xsl:template match="Street" />
</xsl:stylesheet>

注文は完全に正常に機能します。しかしPosition、異なる番号に繰り返し番号がある場合Type、すべてのHouses とsは、繰り返し番号がBlockある最初の場所に配置されます。例えば:TypePosition

<Area>
         <Type>A</Type>
         <Street>
           <Position>5</Position>
           <House>

           --> some elements

           </House>
         </Street>
         <Street>
           <Position>5</Position>
           <Block>

           --> some elements

           </Block>
         </Street>
....
<Area>
     <Type>B</Type>
     <Street>
       <Position>5</Position>
       <House>

       --> some elements

       </House>
     </Street>

Position 5次に、 inの下の要素Type Bがそこから in の下に移動さPosition 5TypeAます。そして、私はそれを望んでいません。ハウスとブロックを配置して、それぞれのタイプとエリアにとどめたいと思います。

これを修正するために XSLT を変更する方法を教えてください。

PS XML タグの名前は、簡略化のために変更されました。また、エディターがサポートしていないため、xslt-2.0 を使用できません。

4

1 に答える 1

2

これを行うには、複合キーが必要です。これは、グループを識別するすべての値の連結であり、あなたの場合はType (親要素の) とPositionです。

<xsl:key name="streetByPosition" match="Street" use="concat(../Type, '|', Position)" />

その後、通常の方法でキーを使用できます

key('streetByPosition', concat(../Type, '|', Position))

次の XSLT を試してください。

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

  <xsl:key name="streetByPosition" match="Street" use="concat(../Type, '|', Position)" />

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

  <!-- for the first Street in each Position -->
  <xsl:template match="Street[generate-id() =
                            generate-id(key('streetByPosition', concat(../Type, '|', Position))[1])]">
    <Street>
      <!-- copy in the Position element once only -->
      <xsl:apply-templates select="Position" />
      <!-- copy in all sub-elements except Position from all matching Streets-->
      <xsl:apply-templates select="
            key('streetByPosition', concat(../Type, '|', Position))/*[not(self::Position)]" />
    </Street>
  </xsl:template>

  <!-- ignore all other Street elements -->
  <xsl:template match="Street" />
</xsl:stylesheet>

注意すべき唯一のことは、連結内の「パイプ」文字は、そのような要素の 2 つの異なる組み合わせが生じないようにするために、 Type要素とPosition要素のいずれにも出現しない限り、任意の文字にすることができるということです。同じキーで。

于 2013-06-14T13:49:20.100 に答える