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.
a source to share
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.
a source to share
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>
a source to share