Is xsl: sequence always nonempty?

I do not understand the output from this stylesheet:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="root/sub"/>
    </xsl:template>

    <xsl:template match="sub">
        <xsl:variable name="seq">
            <xsl:sequence select="*" />
        </xsl:variable>

        <xsl:message>
            <xsl:value-of select="@id" />
            <xsl:text>: </xsl:text>
            <xsl:value-of select="count($seq)" />
        </xsl:message>
    </xsl:template>
</xsl:stylesheet>

for the following XML:

<root>
    <sub id="empty" />
    <sub id="one"><one/></sub>
    <sub id="two"><one/><one/></sub>
    <sub id="three"><one/><one/><one/></sub>
</root>

The output written by the element xsl:messageis:

empty: 1
one: 1
two: 1
three: 1

I was expecting this instead:

empty: 0
one: 1
two: 2
three: 3

Why count($seq)always returns 1 in this case? How would you change the definition of a variable so that I can later check it for emptiness? (A simple one <xsl:variable name='seq' select='*' />will return the expected answer, but not an option ... I want to change the variable betweenin this template and check it for emptiness later).

+3
source share
3 answers

Let me try to answer the question "why" of your question.

If you write the following instructions:

<xsl:variable name="x" select="*" />

$x node. $x node, select. :

<xsl:variable name="x">
    <content />
    <content />
</xsl:variable>

$x node: node of content. count($x) 1. content, $x node: count($x/content).

, , : xsl:variable select, . xsl:variable select, , - .

xsl:sequence xsl:variable. xsl:variable, , 1, .

: xsl:variable, select, , :

<xsl:variable name="x" select="$y/*" />

<xsl:variable name="y">
    <xsl:sequence select="foo" />
</xsl:variable>

count($x), .

+5

, , :

<xsl:variable name="seq" select="*"/>

, 'as':

<xsl:variable name="seq" as="item()*">
        <xsl:sequence select="*" />
</xsl:variable>

, XSLT 2.0. Saxon, , Saxon :

    <xsl:template match="sub" saxon:explain="yes" xmlns:saxon="http://saxon.sf.net/">
    <xsl:variable name="seq">
        <xsl:sequence select="*" />
    </xsl:variable>

    <xsl:message>
        <xsl:value-of select="@id" />
        <xsl:text>: </xsl:text>
        <xsl:value-of select="count($seq)" />
    </xsl:message>
</xsl:template>

, - node :

Optimized expression tree for template at line 6 in :
                    let $seq[refCount=1] as document-node() :=
                      document-constructor
                        child::element()
                    return
                      message
+3

You select the auxiliary nodes, and then count each node - so it will always be 1. You need to count the children, for example:

<xsl:value-of select="count($seq/*)" />

will give you the result you expect.

+2
source

Source: https://habr.com/ru/post/1721624/


All Articles