[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: Sort XML based on Tokenized String of sort by fiel

Subject: RE: Sort XML based on Tokenized String of sort by fields
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 22 May 2008 10:24:24 +0100
RE:  Sort XML based on Tokenized String of sort by fiel
As David suggests, I think I'd go for the approach of generating a
stylesheet. In effect your <REPORT_FORMAT> element defines a miniature
programming language, and a good way of implementing such languages is often
to translate them to XSLT. I've done similar things with report
specifications entered interactively on the screen. You're already doing
dynamic construction/evaluation of XPath expressions, so dynamic
construction of the entire stylesheet (or of the controlling framework, it
can always include/import a fixed module) isn't a major step from that.

Michael Kay
http://www.saxonica.com/  

> -----Original Message-----
> From: Rebecca Sapir [mailto:rsapir@xxxxxxxxxxxxxxxxxxxx] 
> Sent: 22 May 2008 00:21
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject:  Sort XML based on Tokenized String of sort by fields
> 
> 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($strin
> g,',')))"/>
>    </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.

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.