【问题标题】:Arrange nodes under a closed element - XSLT在封闭元素下排列节点 - XSLT
【发布时间】:2013-06-11 04:19:12
【问题描述】:

所以我有这个 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>

排序工作完全正常。 但是,如果我在不同的Type 中有重复的Position 数字,那么我会将所有Houses 和Blocks 安排在第一个Type 中,其中我有重复的Position 数字。 例如:

<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>

然后Type BPosition 5下的元素将从那里移动到TypeAPosition 5下。我不希望那样。我希望安排房屋和街区,但要保留在自己的类型和区域中。

谁能为我提供如何更改我的 XSLT 才能解决此问题的解决方案?

附:为简化起见,更改了 XML 标记的名称。而且我不能使用 xslt-2.0,因为我的编辑器不支持它。

【问题讨论】:

    标签: xml xslt xslt-1.0 xslt-grouping muenchian-grouping


    【解决方案1】:

    为此,您需要一个复合键,它将是标识您的组的所有值的串联,在您的情况下是 Type(父元素的),以及位置

    <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>
    

    唯一需要注意的是,串联中的“竖线”字符可以是任何你喜欢的字符,只要它不在TypePosition中的任何一个中出现即可 元素,以确保此类元素的两个不同组合不会产生相同的键。

    【讨论】:

      猜你喜欢
      • 2013-05-14
      • 1970-01-01
      • 2016-11-26
      • 2016-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多