Check first subnode from node

XML:

    <mode>
        <submode>1</submode>
        <submode>2</submode>
        <submode>3</submode>
        <submode>4</submode>
        <submode>5</submode>
        <submode>6</submode>
        <submode>7</submode>
    </mode>
    <mode>
        <submode>7</submode>
        <submode>8</submode>
        <submode>9</submode>
        <submode>10</submode>
        <submode>11</submode>
        <submode>12</submode>
        <submode>13</submode>
    </mode>
    <mode>
        <submode>14</submode>
        <submode>15</submode>
        <submode>16</submode>
        <submode>17</submode>
        <submode>18</submode>
        <submode>19</submode>
        20</submode>
    </mode>   

      

How to check first <submode>

from each <mode>

(I need to get numbers: 1, 7, 14 ) in a construction like this:

<xsl:template match="submode">
    <xsl:if test="(parent::mode) and (...what?...)">
        ...
    </xsl:if>
    ...
</xsl:template>

      

I don't understand how position () is used here.

+2


a source to share


3 answers


It is usually not true that

position() = 1



evaluates true()

to if the current node has a parent mode and the current node is the first child of submode

its parent.

position()

indicates the position of the current node -list , and this is defined differently depending on how the attribute is specified select

<xsl:apply-templates>

.

For example (assuming the provided XML has a top element that is the parent of the elements mode

) if a template was selected while processing the following:

<xsl:apply-templates select="/*/mode/submode[. = 3]"/>

then

position() = 1



only true for the third child of the submode

first element mode

.

One correct answer:

parent::mode and not(preceding-sibling::submode)

Or it is recommended :

You have a separate template:

<xsl:template match="mode/submode[1]">

In this case, no code inside the template is needed to check if the current node is the first submode

child - this is already known.

+5


a source


To count the number submode

in the previous one mode

if and only if it is the first of the submode

current one mode

, and avoid duplicating code between <xsl:template match="submode">

and <xsl:template match="submode[1]">

:

<!-- Special processing for first submode -->
<xsl:template match="submode[1]">
    <xsl:variable name="previousSubmodes" 
                  select="count(../preceding-sibling::mode/submode)"/>

    <!-- ... Do stuff with count ... -->

    <!-- Perform regular submode processing -->
    <xsl:call-template name="submode"/>

</xsl:template>

<!-- Regular processing for submodes -->
<xsl:template match="submode" name="submode">
    <!--  ... Do whatever ... -->
</xsl:template>

      



Alternatively, you can do invoice processing from the template for mode

. This way, you don't need any special processing for the first one submode

.

<xsl:template match="mode">
    <!-- ... Other processing ... -->

    <xsl:variable name="previousSubmodes" 
                  select="count(preceding-sibling::mode/submode)"/>

    <!-- ... Do stuff with count ... -->

    <!-- Handle submodes; could use select="node()|@*" instead to process 
         everything, not just submodes  -->
    <xsl:apply-templates select="submode"/>

</xsl:template>

<xsl:template match="submode">
    <!--  ... Do whatever ... -->
</xsl:template>

      

+1


a source


Your <xsl:template match=

must read "mode/submode[1]"

.

Then you will have the first of submode

each mode

.

0


a source







All Articles