Xslt gouping问题

时间:2015-01-15 20:58:24

标签: xslt grouping

我有一个像下面的xml

<XYZ>
<Name>abc</Name>
<Year>1984</Year>
<Model>qwe</Model>
<Name>abc</Name>
<Year>1987</Year>
<Model>qwe</Model>
<Name>qweqr</Name>
<Year>1977</Year>
<Model>tryet</Model>
</XYZ>

需要转换为     <XYZ> <Name>abc</Name> <Year>1984</Year> <Year>1987</Year> <Model>qwe</Model> <Name>qweqr</Name> <Year>1977</Year> <Model>tryet</Model> </XYZ>

这里名称可以被视为关键

2 个答案:

答案 0 :(得分:0)

使用XSLT 1.0,可以使用Muenchian Grouping和以下XSLT来完成:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
 <xsl:strip-space elements="*"/>
 <xsl:key name="names" match="Name" use="text()"/>
 <xsl:key name="models" match="Model" use="text()"/>
  <xsl:template match="XYZ">
  <XYZ> 
    <xsl:for-each select="//Name[generate-id()=generate-id(key('names',text())[1])]">
      <xsl:variable name="current" select="."/>
      <xsl:apply-templates select="."/>
      <xsl:apply-templates select="//Name[.=$current]/following-sibling::Year[1]"/>
       <xsl:for-each select="//Name[.=$current]/following-sibling::Model[1]
                             [generate-id()=generate-id(key('models',text())[1])]">
         <xsl:apply-templates select="."/>
       </xsl:for-each>  
      </xsl:for-each>
    </XYZ>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:transform>

结果:

<XYZ>
 <Name>abc</Name>
 <Year>1984</Year>
 <Year>1987</Year>
 <Model>qwe</Model>
 <Name>qweqr</Name>
 <Year>1977</Year>
 <Model>tryet</Model>
</XYZ>

YearModel的重复节点将被删除,因为xsl:for-each中仅选择了唯一值:

<xsl:for-each select="//Name[generate-id()=generate-id(key('names',text())[1])]">

复制了唯一的Name,然后复制了具有当前唯一Name值的前一个Name的所有年份:

<xsl:apply-templates select="//Name[.=$current]/following-sibling::Year[1]"/>  

然后,复制相应的唯一Model节点,第二个xsl:for-each只选择Model<xsl:for-each select="//Name[.=$current]/following-sibling::Model[1] [generate-id()=generate-id(key('models',text())[1])]"> 个节点后的唯一{

}

model

由于使用Muenchian方法对Stackoverflow进行XSLT分组已经有很多答案,我只是推荐Jeni Tennison http://www.jenitennison.com/xslt/grouping/muenchian.xml在本文中的详细解释。

作为XSLT分组的附加参考,您可以查看http://www.dpawson.co.uk/xsl/sect2/N4486.html

更新:根据评论建议,如果不同name值的重复<?xml version="1.0" encoding="UTF-8" ?> <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8 indent="yes" /> <xsl:strip-space elements="*"/> <xsl:key name="names" match="Name" use="text()"/> <xsl:template match="XYZ"> <XYZ> <xsl:for-each select="//Name[generate-id()=generate-id(key('names',text())[1])]"> <xsl:variable name="current" select="."/> <xsl:apply-templates select="."/> <xsl:apply-templates select="//Name[.=$current]/following-sibling::Year[1]"/> <xsl:for-each select="//Name[.=$current]/following-sibling::Model[1] [not(.= preceding-sibling::Name[.=$current] /preceding-sibling::Name[.=$current] /following-sibling::Model)]"> <xsl:apply-templates select="."/> </xsl:for-each> </xsl:for-each> </XYZ> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:transform> 值,则无法使用此功能。调整后的XSLT

name

适用于OP中提供的示例XML以及评论中建议的示例XML - 仅model个唯一name值,可选的多年和model的唯一name值,但也可以为不同的{{1}}列出相同的{{1}}。

答案 1 :(得分:0)

我认为您可以使用此样式表,该样式表使用键选择YearModel(根据其名称对模型进行分组,然后根据其值进行分组)基于其前面的{{1} (分组名称后):

Name