Domanda

Is there a reason why the following two pieces variable definitions should behave differently?

The first definition uses XPath 2 an if statement:

<xsl:variable name="content" select="if ($next-divm)
    then (./following-sibling::node() intersect $next-divm/preceding-sibling::node())
    else (./following-sibling::node())"/>

The second definition uses <xsl:choose> to reach the same result (or so I'd think):

<xsl:variable name="content1">
    <xsl:choose>
        <xsl:when test="$next-divm">
            <xsl:copy-of select="./following-sibling::node() intersect $next-divm/preceding-sibling::node()"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy-of select="./following-sibling::node()"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

However, these two techniques lead to two different results when $content is output using

<xsl:apply-templates select="$content" mode="keep"/>

In the first case all the content is correctly copied (i.e all the elements and text nodes are preserved), while in the latter only the text nodes are preserved. This strange behaviour may be linked to the following other two templates.

<xsl:template match="node()[not(self::divm)][./preceding-sibling::divm]"/>

<xsl:template match="node()[not(self::divm)][./preceding-sibling::divm]" mode="keep">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="keep"/>
    </xsl:copy>
</xsl:template>

Regardless of my specific templates, I would like to know why the two <xsl:variable> styles can lead to different results.

È stato utile?

Soluzione

The XPath if is returning the original nodes from the input, still attached to their original contexts in the input tree. The choose version is returning new nodes that are copies of the input nodes, and when you navigate the preceding-sibling:: axis from these nodes you're only looking at the temporary tree in the variable, not the nodes' original context in the source XML.

If you want to capture the original nodes rather than copies in the xsl:choose variant then use xsl:sequence instead of xsl:copy-of. You will also need to make the variable typed by adding something like as="node()*". Section 9.4 of the XSLT 2.0 spec explains why (my bold):

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. [...] The value of the variable is a single node, the document node of the temporary tree. The content of the document node is formed from the result of evaluating the sequence constructor

If you do provide as="node()*" then the nodes produced by the sequence constructor (i.e. the content of the xsl:variable element) are used as-is rather than forming the content of a new implicit document node.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top