xsl-list
[Top] [All Lists]

[xsl] Sort XML based on Tokenized String of sort by fields

2008-05-21 16:21:18
I am also using the SAXON parser. 
XSLT version 2

I am trying to sort by a tokenized string. I get an ORDER_BY string with field 
names to sort by which are separated by commas. 

The number of fields in the order_by string names can vary!!!

The X and X_ROW names are not constant. They can vary and are therefore passed 
in the PARENT_NODE and CHILD_NODE fields.
For example: 

The XML I get is formatted as  

<REPORT>
      <REPORT_HDR>
      ...
      </REPORT_HDR>
            <REPORT_FORMAT>
                        <ORDER_BY> DATE, ID_1, ID_2, TYPE</ORDER_BY>
                        <PARENT_NODE>X</PARENT_NODE>
                        <CHILD_NODE>X_ROW</CHILD_NODE>
            </REPORT_FORMAT>
            <X>
                <X_ROW>             
                              <DATE></DATE>
                              <ID_1></ID_1>
                              <TYPE ></TYPE>
                              ...
                    </X_ROW>
                <X_ROW>             
                              <DATE></DATE>
                              <ID_1></ID_1>
                              <TYPE ></TYPE>
                              ...
                    </X_ROW>
                <X_ROW>             
                              <DATE></DATE>
                              <ID_1></ID_1>
                              <TYPE ></TYPE>
                              ...
                    </X_ROW>
                <X_ROW>             
                              <DATE></DATE>
                              <ID_1></ID_1>
                              <TYPE ></TYPE>
                              ...
                    </X_ROW>
</REPORT>

In this case I want to sort the X/X_ROW's by DATE then ID_1 then ID_2 etc

This is one solution I have so far...
(The other one is below which uses recursion instead of tokenize)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0" 
xmlns:saxon="http://saxon.sf.net/";>
<xsl:variable name="PATH" select="REPORT/REPORT_FORMAT/PARENT_NODE" />
<xsl:variable name="CHILD" select="REPORT/REPORT_FORMAT/CHILD_NODE" />
<xsl:variable name="ORDER_BY" select="REPORT/REPORT_FORMAT/ORDER_BY"/>
<xsl:variable name="ORDER_BY_TOKEN" select="tokenize($ORDER_BY,',')"/>
            
<xsl:template match="REPORT/*">

<xsl:choose>

 <xsl:when test="local-name() = $PATH">

  <xsl:copy>

    <xsl:for-each select="*">
     <xsl:sort select="saxon:evaluate(normalize-space($ORDER_BY_TOKEN[1]))"/>   
      
     <xsl:sort select="saxon:evaluate(normalize-space($ORDER_BY_TOKEN[2]))"/>   
        
     <xsl:sort select="saxon:evaluate(normalize-space($ORDER_BY_TOKEN[3]))"/>   
        
     <xsl:sort select="saxon:evaluate(normalize-space($ORDER_BY_TOKEN[4]))"/>   
        
     <xsl:copy-of select="."/>                                                  
     
    </xsl:for-each>

  </xsl:copy>

 </xsl:when>

 <xsl:otherwise>

  <xsl:copy-of select="."/>                                

 </xsl:otherwise>

</xsl:choose>

</xsl:template>

<xsl:template match="*">

<xsl:copy>
  <xsl:apply-templates/>
</xsl:copy>

</xsl:template>

</xsl:stylesheet>

My issue of course is that I am hard coding the ORDER_BY_TOKEN item that I 
want. In truth there are a variable number of fields that can get passed to me. 

Ideally if I could surround the sorts with a for loop that would be what I am 
looking for. But this does not work:
  <xsl:for-each select="*">

    <xsl:for-each select="1 to count($ORDER_BY_TOKEN)">
      <xsl:sort select="saxon:evaluate(normalize-space($ORDER_BY_TOKEN[.]))"/> 
      <xsl:copy-of select="."/>        
    </xsl:for-each>

  </xsl:for-each>


Instead of tokenizing I tried a recursive function. This will perform the sorts 
but not consecutively. So in effect the last sort is really the only one that 
gets applied. Ie. it does not have the effect of sort by Date then id_1 then 
id_2 then...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0" 
xmlns:saxon="http://saxon.sf.net/";>

<xsl:variable name="PATH" select="REPORT/REPORT_FORMAT/PARENT_NODE" />
<xsl:variable name="ORDER_BY" select="REPORT/REPORT_FORMAT/ORDER_BY"/>


<xsl:template match="REPORT/*">

<xsl:choose>

<xsl:when test="local-name() = $PATH">

  <xsl:copy>

    <xsl:call-template name="tokenize">
      <xsl:with-param name="string" select="$ORDER_BY" />
    </xsl:call-template>

  </xsl:copy>

  </xsl:when>

  <xsl:otherwise>
   <xsl:copy-of select="."/>                                
  </xsl:otherwise>

</xsl:choose>
</xsl:template>

<xsl:template match="*">
  <xsl:copy>
       <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<xsl:template name="tokenize">

 <xsl:param name="string" />

 <xsl:choose>

  <xsl:when test="contains($string, ',')">

   <xsl:apply-templates>
    <xsl:sort 
select="saxon:evaluate(normalize-space(substring-before($string,',')))"/>
   </xsl:apply-templates>

  <xsl:call-template name="tokenize">
    <xsl:with-param name="string" select="substring-after($string, ',')" />
  </xsl:call-template>

 </xsl:when>

 <xsl:otherwise>
  <xsl:copy>

   <xsl:apply-templates>
    <xsl:sort select="saxon:evaluate(normalize-space($string))"/>           
   </xsl:apply-templates>

  <xsl:copy-of select="."/>
 </xsl:copy>
 </xsl:otherwise>

</xsl:choose>                        

</xsl:template>

</xsl:stylesheet>
 
Any help would be greatly appreciated.

Thanks.






Merlin Securities - #1 Prime Broker North America and #1 Prime Broker Single 
Strategy Funds - Global Custodian 2007
#1 Prime Broker for Hedge Funds under $1 Billion - Alpha Survey 2007



 
--------------------------------------------------------------------------
This message contains information from Merlin Securities, LLC, or from one of 
its affiliates, that may be confidential and privileged. If you are not an 
intended recipient, please refrain from any disclosure, copying, distribution 
or use of this information and note that such actions are prohibited. If you 
have received this transmission in error, please notify the sender immediately 
by telephone or by replying to this transmission.
 
Merlin Securities, LLC is a registered broker-dealer. Services offered through 
Merlin Securities, LLC are not insured by the FDIC or any other Federal 
Government Agency, are not deposits of or guaranteed by Merlin Securities, LLC 
and may lose value. Nothing in this communication shall constitute a 
solicitation or recommendation to buy or sell a particular security.



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--