如何对元素进行排序并根据唯一元素或ID对它们进行分组

时间:2011-05-16 07:18:36

标签: xslt

如何根据“CorporationID”对元素进行排序并对它们进行分组..

我有一个类似下面的xml负载......

 <corporationActions>
  <corporationAction>
    <ActionID>5530974</ActionID>
    <CorporationID>1044294</CorporationID>
    <ActionDate>2009-05-03</ActionDate>
    <ActionType>Articles of Organization2</ActionType>
    <ActionNotes></ActionNotes>
    <DocumentNumber>20110258775-68</DocumentNumber>
    <NumberofPages>4</NumberofPages>
  </corporationAction>
  <corporationAction>
    <ActionID>5530975</ActionID>
    <CorporationID>1044294</CorporationID>
    <ActionDate>2009-05-03</ActionDate>
    <ActionType>Miscellaneous</ActionType>
    <ActionNotes></ActionNotes>
    <DocumentNumber>20110258777-80</DocumentNumber>
    <NumberofPages>2</NumberofPages>
  </corporationAction>
</corporationActions>

我需要首先根据 CorporationID 对元素进行排序,然后在 CorporationID 重复时将它们分组..就像下面的paylaod

<corporationActions>
    <corporationAction>
        <CorporationID>1044294</CorporationID>
        <corporationActionDetails>
            <ActionID>5530974</ActionID>
            <ActionDate>2009-05-03</ActionDate>
            <ActionType>Articles of Organization2</ActionType>
        </corporationActionDetails>
        <corporationActionDetails>
            <ActionID>5530975</ActionID>
            <ActionDate>2009-05-03</ActionDate>
            <ActionType>Miscellaneous</ActionType>
        </corporationActionDetails>
    </corporationAction>
</corporationActions>

谢谢&amp;问候, anvv sharma

2 个答案:

答案 0 :(得分:1)

这是一个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="kcorpActByID" match="corporationAction"
  use="CorporationID"/>

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

 <xsl:template match=
 "corporationAction|CorporationID
 |ActionNotes|DocumentNumber|NumberofPages"/>

 <xsl:template match=
  "corporationAction
    [generate-id()
    =
     generate-id(key('kcorpActByID', CorporationID)[1])
     ]">
  <corporationAction>
   <xsl:copy-of select="CorporationID"/>
   <xsl:apply-templates mode="copy"
    select="key('kcorpActByID',CorporationID)" />
  </corporationAction>
 </xsl:template>

 <xsl:template match="corporationAction" mode="copy">
  <corporationActionDetails>
   <xsl:apply-templates/>
  </corporationActionDetails>
 </xsl:template>
</xsl:stylesheet>

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

<corporationActions>
  <corporationAction>
    <ActionID>5530974</ActionID>
    <CorporationID>1044294</CorporationID>
    <ActionDate>2009-05-03</ActionDate>
    <ActionType>Articles of Organization2</ActionType>
    <ActionNotes></ActionNotes>
    <DocumentNumber>20110258775-68</DocumentNumber>
    <NumberofPages>4</NumberofPages>
  </corporationAction>
  <corporationAction>
    <ActionID>5530975</ActionID>
    <CorporationID>1044294</CorporationID>
    <ActionDate>2009-05-03</ActionDate>
    <ActionType>Miscellaneous</ActionType>
    <ActionNotes></ActionNotes>
    <DocumentNumber>20110258777-80</DocumentNumber>
    <NumberofPages>2</NumberofPages>
  </corporationAction>
</corporationActions>

产生了想要的正确结果

<corporationActions>
   <corporationAction>
      <CorporationID>1044294</CorporationID>
      <corporationActionDetails>
         <ActionID>5530974</ActionID>
         <ActionDate>2009-05-03</ActionDate>
         <ActionType>Articles of Organization2</ActionType>
      </corporationActionDetails>
      <corporationActionDetails>
         <ActionID>5530975</ActionID>
         <ActionDate>2009-05-03</ActionDate>
         <ActionType>Miscellaneous</ActionType>
      </corporationActionDetails>
   </corporationAction>
</corporationActions>

请注意:由于使用和覆盖身份模板而增加了灵活性。与<xsl:copy-of select="ActionID|ActionDate|ActionType"/>相反,我们使用:<xsl:apply-templates/>,这可以确保当前节点的任何子节点都可以以我们想要的任何方式处理(并在单独的模板中进一步指定)。

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

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

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

 <xsl:template match="/*">
  <xsl:for-each-group select="corporationAction"
       group-by="CorporationID">
   <xsl:sort select="number(CorporationID)"/>

   <corporationAction>
    <xsl:sequence select="CorporationID"/>
    <xsl:apply-templates mode="copy"
     select="current-group()" />
   </corporationAction>
  </xsl:for-each-group>
 </xsl:template>

 <xsl:template match="corporationAction" mode="copy">
  <corporationActionDetails>
   <xsl:apply-templates/>
  </corporationActionDetails>
 </xsl:template>

  <xsl:template match=
 "corporationAction|CorporationID
 |ActionNotes|DocumentNumber|NumberofPages"/>
</xsl:stylesheet>

请注意:使用<xsl:for-each-group>current-group()功能进行简化分组。

答案 1 :(得分:0)

此解决方案使用Muenchian方法:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
 <xsl:output indent="yes"/>

 <xsl:key name="bycorporationid" match="corporationActions/corporationAction" use="CorporationID"/>

 <xsl:template match="corporationActions">
  <corporationActions>
   <xsl:for-each select="corporationAction[count(. | key('bycorporationid', CorporationID)[1]) = 1]">

    <xsl:sort select="CorporationID" />

     <corporationAction>
      <CorporationID><xsl:value-of select="CorporationID"/></CorporationID>

       <xsl:for-each select="key('bycorporationid',CorporationID)">
        <corporationActionDetails>
          <xsl:copy-of select="ActionID"/>
          <xsl:copy-of select="ActionDate"/>
          <xsl:copy-of select="ActionType"/>
        </corporationActionDetails>
      </xsl:for-each>

     </corporationAction>

   </xsl:for-each>
  </corporationActions>
 </xsl:template>

</xsl:stylesheet>