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