Thanks, Jeni. That works great in both Saxon and MarkLogic. 

And thanks for the explanation.  I'm going to contact MarkLogic support about 
the behavior and see what comes of it.

-James




-----Original Message-----
From: [email protected] 
[mailto:[email protected]] On Behalf Of Jeni Tennison
Sent: Thursday, January 13, 2011 12:25 PM
To: General MarkLogic Developer Discussion
Subject: Re: [MarkLogic Dev General] Differing element() & document-node() XSLT 
behavior in Saxon vs. MarkLogic

Hi James,

I believe that this is a MarkLogic bug, but you can probably work around it. 
You have:

   <xsl:template match="/" name="root">
       <xsl:param name="count" select="1"/>
       <xsl:param name="document-tree">
           <xsl:apply-templates select="/" mode="other"/>
       </xsl:param>
       ...
   </xsl:template>

The $document-tree parameter should be set to a temporary tree (ie a document 
node with children determined by whatever you get by the <xsl:apply-templates 
/>). See:

  http://www.w3.org/TR/xslt20/#temporary-trees

which says:

  "A document node is created implicitly when evaluating an xsl:variable, 
xsl:param, or xsl:with-param element that has non-empty content and that has no 
as attribute."

It looks as though MarkLogic isn't doing this, but it assigning to 
$document-tree whatever you get from the <xsl:apply-templates /> (ie an element 
node) rather than creating the implicit document node.

You can probably work around it by explicitly including an as attribute and a 
xsl:document instruction as follows:

       <xsl:param name="document-tree" as="document-node()">
           <xsl:document>
              <xsl:apply-templates select="/" mode="other"/>
           </xsl:document>
       </xsl:param>

(Untested.)

Cheers,

Jeni

On 13 Jan 2011, at 17:54, James Sulak wrote:

> Hello,
> 
> I've noticed that MarkLogic is very literal when it comes to the difference 
> between elements and document nodes in a way that surprised me when it came 
> to XSLT.  A simple example:
> 
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";   
>    version="2.0">
> 
>   <xsl:template match="/">
>       <document-node />
>   </xsl:template>
> 
>   <xsl:template match="/*">
>       <root-element />
>   </xsl:template>
> 
> </xsl:stylesheet>
> 
> When I call this stylesheet using xdmp:xslt-invoke("test.xslt", 
> document("test.xml")) I get the result <document-node />.  When I call it 
> using xdmp:xslt-invoke("test.xslt", document("test.xml")/*), I get the result 
> <root-element />.  
> 
> That's fair enough I suppose, since Marklogic is strictly following the type 
> of the node passed to the XSLT.  It makes it annoying to incorporate 
> already-existing XSLTs into Marklogic queries, since we will have to be very 
> careful to always pass in a document node to a transform, even when 
> constructing XML on the fly.  This is also different than the behavior I'm 
> used to in eXist, which treated any XML passed to its transform:transform() 
> as a document.  I like the eXist behavior better, but I can understand 
> thinking otherwise.
> 
> However, this becomes a more serious problem when trying to incorporate 
> multi-stage transforms.  The behavior in Saxon and MarkLogic differs enough 
> so that the transform must take into account the differing engines to get 
> consistent results.  For example:
> 
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
> version="2.0">
> 
>    <xsl:template match="/" name="root">
>        <xsl:param name="count" select="1"/>
>        <xsl:param name="document-tree">
>            <xsl:apply-templates select="/" mode="other"/>
>        </xsl:param>
> 
>        <xsl:message
>            select="if ($document-tree instance of document-node()) 
>            then 'document-node()' 
>            else 'element()'"/>
> 
>        <xsl:choose>
>            <xsl:when test="$count lt 2">
>                <xsl:call-template name="root">
>                    <xsl:with-param name="document-tree" 
> select="$document-tree"/>
>                    <xsl:with-param name="count" select="$count + 1"/>
>                </xsl:call-template>
>            </xsl:when>
>            <xsl:otherwise>
>                <xsl:choose>
>                    <xsl:when test="$document-tree instance of 
> document-node()">
>                        <xsl:message>For Saxon (document-node())</xsl:message>
>                        <xsl:apply-templates select="$document-tree/node()"/>
>                    </xsl:when>
>                    <xsl:otherwise>
>                        <xsl:message>For MarkLogic (element())</xsl:message>
>                        <xsl:apply-templates select="$document-tree"/>
>                    </xsl:otherwise>
>                </xsl:choose>
>            </xsl:otherwise>
>        </xsl:choose>
> 
>    </xsl:template>
> 
>    <xsl:template match="@*|node()" mode="#all">
>        <xsl:copy>
>            <xsl:apply-templates select="@*|node()" mode="#current"/>
>        </xsl:copy>
>    </xsl:template>
> 
> </xsl:stylesheet>
> 
> This transform should recurse once and return the original XML.  The specific 
> test input is unimportant, but I've been using:
> 
> <root>
>    <child1/>
>    <child2/>
> </root>
> 
> When run in Saxon, I get this as my console output:
> 
> document-node()
> document-node()
> For Saxon (document-node())
> 
> When I execute it in Marklogic, passing it a document-node, I get in the log:
> 
> element-node()
> element-node()
> For MarkLogic (element())
> 
> If I leave out the xsl:when/xsl:otherwise, I either get infinite looping in 
> Saxon or lose the root element in MarkLogic, depending on whether I use 
> $document-tree/node() or $document-tree for the final apply-templates.  
> 
> I'm not confident enough in my XSLT/XPath knowledge to know when behavior is 
> "correct," but it looks to me that the Saxon behavior maintains the type 
> properly.  
> 
> In any case, is this a MarkLogic implementation bug or just a differing 
> interpretation of the spec?  
> 
> Thanks,
> 
> James
> 
> 
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> 

-- 
Jeni Tennison
http://www.jenitennison.com

_______________________________________________
General mailing list
[email protected]
http://developer.marklogic.com/mailman/listinfo/general
_______________________________________________
General mailing list
[email protected]
http://developer.marklogic.com/mailman/listinfo/general

Reply via email to