1
votes

how do i sort the elements based on "CorporationID" and group them..

I have an xml payload something like the below one ...

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

i need to first sort the elements based on CorporationID and then group them if the CorporationID s are repeating.. like the below 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>

Thanks & Regards, anvv sharma

2

2 Answers

1
votes

This is an XSLT 1.0 grouping (Muenchian method) solution, that is mostly in push-style using templates and no <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>

When this transformation is applied to the provided XML document:

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

the wanted, correct result is produced:

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

Do note: The added flexibility due to the use and overriding of the identity template. In contrast of <xsl:copy-of select="ActionID|ActionDate|ActionType"/> we use: <xsl:apply-templates/> and this assures that any of the children of the current node can be processed in any way we want (and further specify in separate templates).

II. XSLT 2.0 solution:

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

Do note: the simplified grouping using <xsl:for-each-group> and the current-group() function.

0
votes

This solution uses Muenchian method:

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