Sunday, May 11, 2008

Some differences between XQuery 1.0 and XSLT 2.0

I can think, of following differences between XQuery 1.0 and XSLT 2.0:

1. In XQuery 1.0, functions need to be declared before use. While in XSLT 2.0, functions may be defined anywhere in the stylesheet (provided, that the function body is a child of the element, xsl:stylesheet).

2. In XQuery 1.0, the XML Schema namespace, http://www.w3.org/2001/XMLSchema is not required to be declared for using the prefix, xs:. While in XSLT 2.0 XML Schema namespace needs to be declared, if any reference to the prefix xs: is made in the XSLT stylesheet.

3. XQuery 1.0 has (seems to me) stronger static typing than XSLT 2.0. For e.g., to return a xs:string value from a function in XQuery 1.0, we cannot simply write, $people/person[fname = $fName]/lname/text(). But instead we have to do for example, xs:string($people/person[fname = $fName]/lname/text()).
While in XSLT 2.0, an expression like $people/person[fname = $fName]/lname is able to return a xs:string value (if element 'lname' contains a text only data).

4. Moreover, an XQuery program is not a template based program description (as is a XSLT, stylesheet). The XQuery syntax looks to me, a mix of procedural and declarative syntax.

It's also true that, XSLT and XQuery are both functional in nature. But that's a similarity, between these two languages!

Following are an XQuery 1.0 and XSLT 2.0 examples which illustrate the above points:

Input XML:
<?xml version="1.0" encoding="UTF-8"?>
  <people>
    <person>
      <fname>Mukul</fname>
      <lname>Gandhi</lname>
    </person>
    <person>
      <fname>Rohit</fname>
      <lname>Rawat</lname>
    </person>
  </people>

XQuery program:
declare namespace my = "http://localhost/functions";

declare function my:getLastName($people as element(), $fName as xs:string)
as xs:string
{
   xs:string($people/person[fname = $fName]/lname/text())  
};

<person>
  <fname>Mukul</fname>
  <lname>{my:getLastName(doc("../Data/test.xml")/people, "Mukul")}</lname>
</person>

XSLT 2.0 stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:my="http://localhost/functions"
                exclude-result-prefixes="xs my">

<xsl:output method="xml" indent="yes" />

<xsl:template match="/">
  <person>
    <fname>Mukul</fname>
    <lname><xsl:value-of select="my:getLastName(people,'Mukul')" /></lname>
  </person>
</xsl:template>

<xsl:function name="my:getLastName" as="xs:string">
  <xsl:param name="people" as="element()" />
  <xsl:param name="fName" as="xs:string" />

  <xsl:sequence select="$people/person[fname = $fName]/lname" />

</xsl:function>

</xsl:stylesheet>


Michael Kay shared following observation on xsl-list:
XQuery tends to work better when you want to extract a small amount of information from a large document and ignore the rest. XSLT tends to work better if you want to keep most things the same and make a few small changes. Of course there's a range of tasks between those extremes.

2 comments:

vladimir said...

1. The example about static typing is not perfectly valid. The difference is in allowing implicit cast in the xslt. The cast exists anyway.

2. I would point to a drastically difference between "for" construct in xpath 2.0 and the one in the xquery.

I do not understand WG's reasoning here.

3. The other difference is advanded work with regex in xslt 2.0 "xsl:analyze-string".

4. tunnel parameters, the feature you can model in xquery in no way.

5. xsl:result-document to to produce multiple results in xquery.

Mukul Gandhi said...

Thanks for your remarks ...

I think static typing is more about asking the programmer to specify data typing in the code. So I would think that an explicit cast is a stronger static typing feature than implicit cast.