如何在一个封闭元素下组织(分组)节点——XSLT



我已经尝试过用XSLT 1.0对XML进行简单分组,并且成功了,但是这里我有一些更复杂的情况,实际上是不同的情况。XML结构是这样的

<Main>
 <TB>
    --> some elements and stuff - not relevant
   <City>
     <Area>
       <Position>5</Position>
       <House>
       --> some elements and stuff
       </House>
     </Area>
     <Area>
       <Position>5</Position>
       <Block>
       --> some elements and stuff
       </Block>
     </Area>
     <Area>
       <Position>6</Position>
       <House>
       --> some elements and stuff
       </House>
     </Area>
     <Area>
       <Position>6</Position>
       <Block>
       --> some elements and stuff
       </Block>
     </Area>
   </City>
   <City>
   --> same structure but with several repetitions of Position 7 and 8.
   </City>
 </TB>
</Main>

我需要的是将处于相同位置的Block s和House s分组,并去掉位置号的重复。例如,它会变成这样:

   <City>
     <Area>
       <Position>5</Position>
       <House>
       --> some elements and stuff
       </House>
       <Block>
       --> some elements and stuff
       </Block>
     </Area>
     <Area>
       <Position>6</Position>
       <House>
       --> some elements and stuff
       </House>
       <Block>
       --> some elements and stuff
       </Block>
     </Area>
   </City>
   <City>
   --> same structure for Position 7 and 8.
   </City>

这比较困难,因为位置不是区域的属性,所以我基本上必须确定区域的位置值,然后抓住相同位置下的House和Block,并将它们放在一起,用相同的<Area> </Area>包围。

对我来说,这看起来像一个相当标准的Muenchian分组问题,按Position分组Area元素(不是HouseBlock元素)。

<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="areaByPosition" match="Area" use="Position" />
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>
  <!-- for the first Area in each Position -->
  <xsl:template match="Area[generate-id() =
                            generate-id(key('areaByPosition', Position)[1])]">
    <Area>
      <!-- copy in the Position element once only -->
      <xsl:apply-templates select="Position" />
      <!-- copy in all sub-elements except Position from all matching Areas -->
      <xsl:apply-templates select="
            key('areaByPosition', Position)/*[not(self::Position)]" />
    </Area>
  </xsl:template>
  <!-- ignore all other Area elements -->
  <xsl:template match="Area" />
</xsl:stylesheet>

假设文档中没有其他命名为Area的元素,如果任何"某些元素和东西"可能被命名为Area,那么您需要更具体一点,例如将分组限制为City的直接子Area元素:

<xsl:key name="areaByPosition" match="City/Area" use="Position" />
<xsl:template match="City/Area[generate-id() =
                               generate-id(key('areaByPosition', Position)[1])]"
              priority="2">
  ...
</xsl:template>
<xsl:template match="City/Area" priority="1" />

(带有明确的优先级,因为如果不这样做,两个模板将具有相同的默认优先级0.5)

相关内容

  • 没有找到相关文章

最新更新