在封闭元素(XSLT)下安排节点



所以我有这个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数字那么我得到所有的House s和Block s排列在第一个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下的元素将从那里移动到TypeA中的Position 5下。我不希望那样。我想把房子和街区安排在各自的类型和区域内。

谁能给我提供解决方案,我必须如何改变我的XSLT,以解决这个问题?

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

要做到这一点,您需要您将需要一个复合键,它将是标识您的组的所有值的连接,在您的情况下,类型(父元素)和位置

<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>
唯一需要注意的是,连接中的'pipe'字符可以是您喜欢的任何字符,只要它不出现在TypePosition元素中,以确保这类元素的两个不同组合不会产生相同的键。

相关内容

  • 没有找到相关文章

最新更新