2013-05-20 31 views
2

)我试过用XSLT 1.0简单地将XML分组,但它在这里有一些更复杂和实际上不同的情况。 所以XML结构基本上是这样的:如何在一个封闭的元素下组织(组)(XSLT

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

这是很难,因为位置不是区域的属性,所以我基本上有识别区域的位置的值,然后抓住众议院和阻止如果落在相同的位置,并将它们放在一起包围在一起<Area> </Area>

回答

3

这看起来像一个相当标准的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,那么你需要更具体一点,例如限制分组到Area元素是City的直接孩子:

<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相同default priority

+0

这工作得很好,直到我真的找到了不允许的东西。比如我有' ......喇嘛喇嘛' 然后,我在'同一位置5'它从B城下位置5元素和位置5中的元素下安排他们城市A. 我想要它命令的房屋和块,但留在同一个城市。 – Syspect

+0

@Syspect如果你想通过'Position'和包含'City'名称来对'Area'元素进行分组,你需要在分组键的定义中包含相关的东西,比如'use =“concat(../ @name,'|',Position)“'和分组谓词,如'key('areaByPosition',concat(../@name,'|',Position)[1]' –