XSLT按值分组

时间:2011-09-13 10:29:43

标签: xml xslt

我有XML文档

<Contracts>   
    <Contract>
        <F1>key1</F1>
        <F2>2345</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key1</F1>
        <F2>34562</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract> 
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract> 
    <Contract>
        <F1>key2</F1>
        <F2>41575</F2>
        <F3>val</F3>
        <F4>bal</F4>
    </Contract>
</Contracts>

我需要按Contracts/Contract/F1(key1,key2)对这些合同进行分组,以获得此结果:

<Contracts>
    <Set>
        <Contract>
            <F1>key1</F1>
            <F2>2345</F2>
            <F3>val</F3>
            <F4>dal</F4>
        </Contract>
        <Contract>
            <F1>key1</F1>
            <F2>34562</F2>
            <F3>val</F3>
            <F4>dal</F4>
        </Contract>
    <Set>
    <Set>
        <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
        </Contract> 
        <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
        </Contract> 
        <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
        </Contract>
   </Set>
</Contracts>

如何使用XSLT进行操作?

2 个答案:

答案 0 :(得分:4)

<强>予。 XSLT 1.0解决方案(Muenchian分组,没有xsl:for-each):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kContrByF1" match="Contract" use="F1"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match=
  "Contract[not(generate-id()
               =
                generate-id(key('kContrByF1', F1)[1])
                )
            ]"/>

 <xsl:template match="Contract">
  <Contract>
   <Set>
    <xsl:copy-of select="key('kContrByF1', F1)"/>
   </Set>
  </Contract>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<Contracts>
    <Contract>
        <F1>key1</F1>
        <F2>2345</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key1</F1>
        <F2>34562</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>41575</F2>
        <F3>val</F3>
        <F4>bal</F4>
    </Contract>
</Contracts>

产生了想要的正确结果

<Contracts>
   <Contract>
      <Set>
         <Contract>
            <F1>key1</F1>
            <F2>2345</F2>
            <F3>val</F3>
            <F4>dal</F4>
         </Contract>
         <Contract>
            <F1>key1</F1>
            <F2>34562</F2>
            <F3>val</F3>
            <F4>dal</F4>
         </Contract>
      </Set>
   </Contract>
   <Contract>
      <Set>
         <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
         </Contract>
         <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
         </Contract>
         <Contract>
            <F1>key2</F1>
            <F2>41575</F2>
            <F3>val</F3>
            <F4>bal</F4>
         </Contract>
      </Set>
   </Contract>
</Contracts>

<强> II。 XSLT 2.0解决方案:

    

 <xsl:template match="/*">
     <Contracts>
       <xsl:for-each-group select="Contract" group-by="F1">
         <Contract>
          <Set>
            <xsl:sequence select="current-group()"/>
          </Set>
         </Contract>
       </xsl:for-each-group>
     </Contracts>
 </xsl:template>
</xsl:stylesheet>

同样,当在同一个XML文档(上面)上应用此转换时,会产生相同的正确结果。

请注意:

  1. 使用xsl:for-each-group指令。

  2. 使用current-group()功能。

答案 1 :(得分:1)

使用XSL密钥和Muenchian分组。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="kContract" match="Contract" use="F1" />

  <xsl:template match="Contracts">
    <xsl:copy>
      <xsl:for-each select="
        Contract[
          generate-id() = generate-id(key('kContract', F1)[1])
        ]
      ">
        <Set>
          <xsl:copy-of select="key('kContract', F1)" />
        </Set>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

此样式表可准确生成所需的输出。

相关问题