xsl-list
[Top] [All Lists]

order-by vs xsl:sort

2005-04-29 04:42:54

I've been toying to see how to express xquery's order by in terms of
xsl. (There's a question at the end, bonus points for anyone not called
Michael who even gets that far:-)

here's an example xquery


let $data1:=
<a>
<z id="a"><y id="1"/></z>
<z id="b"><y id="2"/></z>
<z id="c"><y id="3"/></z>
<z id="d"><y id="4"/></z>
<z id="e"><y id="5"/></z>
</a>
return
let $data2:=
<a>
<z id="s"><y id="6"/></z>
<z id="t"><y id="7"/></z>
<z id="u"><y id="8"/></z>
</a>
return

for $i in $data1/z/y, $j in $data2/z/y
order by ($j/@id - $i/@id)
return
concat($i/../@id,$j/../@id)



and here's its output (linebreak added after the xml delcn by hand)

$ saxon8q  order.xq
<?xml version="1.0" encoding="UTF-8"?>
es ds et cs dt eu bs ct du as bt cu at bu au

Things to note about this are
a) the sort key cuts across the diagonal, you can't just sort the i and j
   axes separately. So you can't simply make this into two nested
   xsl:for-each each with separate xsl:sort's.
b) the final result uses data accessed by the parent axis from the items
   in the sorted sequence so you can't simply build a temporary tree
   that holds a sequence of elements modelling the tuple with  copies of
   the items in the sequence as then stuff in the parent axis is lost.

Current best plan is the following XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";   
version="2.0"   


<xsl:variable name="data1" as="item()">
<a>
<z id="a"><y id="1"/></z>
<z id="b"><y id="2"/></z>
<z id="c"><y id="3"/></z>
<z id="d"><y id="4"/></z>
<z id="e"><y id="5"/></z>
</a>
</xsl:variable>

<xsl:variable name="data2" as="item()">
<a>
<z id="s"><y id="6"/></z>
<z id="t"><y id="7"/></z>
<z id="u"><y id="8"/></z>
</a>
</xsl:variable>

<xsl:template name="x">

<xsl:variable name="is" select="$data1/z/y"/>
<xsl:variable name="ci" select="count($is)"/>
<xsl:variable name="js" select="$data2/z/y"/>
<xsl:variable name="cj" select="count($js)"/>

<xsl:for-each select="0 to ($ci * $cj)-1">
<xsl:sort select="$js[(current() idiv $ci) +1]/@id - $is[(current()  mod 
$ci)+1]/@id"/>
<xsl:sequence select="concat($is[(current()  mod $ci)+1]/../@id,$js[(current() 
idiv $ci) +1]/../@id)"/>
</xsl:for-each>

</xsl:template>

</xsl:stylesheet>





which works:

$ saxon8 -it x order.xsl
<?xml version="1.0" encoding="UTF-8"?>
es ds et cs dt eu bs ct du as bt cu at bu au

and I think would be automatically generatable in an xquery to xslt
conversion program, although the indexes get messy if there are more
sequences than two involved, and the constraints on xsl:sort being first
mean that you can't make it look nicer by using variables to hold the
calculated indices.

Is this approach plausible? and if so can it be made a bit less ugly?
If not, is there a more plausible approach?

David

________________________________________________________________________
This e-mail has been scanned for all viruses by Star. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________

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



<Prev in Thread] Current Thread [Next in Thread>