Subject: RE: [xsl] Sort XML based on Tokenized String of sort by fields From: "Michael Kay" <mike@xxxxxxxxxxxx> Date: Thu, 22 May 2008 10:24:24 +0100 |
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: [xsl] 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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Sort XML based on Tokeniz, David Carlisle | Thread | Re: [xsl] Sort XML based on Tokeniz, Michael Ludwig |
Re: [xsl] Sort XML based on Tokeniz, David Carlisle | Date | [xsl] xslt architecture, Andrew Welch |
Month |