'Exclude first element of a certain type when doing apply-templates

This is my source XML:

    <DEFINITION>
        <DEFINEDTERM>criminal proceeding</DEFINEDTERM>
        <TEXT> means a prosecution for an offence and includes&#160;&#150;</TEXT>
        <PARAGRAPH>
            <TEXT>a proceeding for the committal of a person for trial or sentence for an offence; and</TEXT>
        </PARAGRAPH>
        <PARAGRAPH>
            <TEXT>a proceeding relating to bail&#160;&#150;</TEXT>
        </PARAGRAPH>
        <TEXT>but does not include a prosecution that is a prescribed taxation offence within the meaning of Part III of the Taxation Administration Act 1953 of the Commonwealth;</TEXT>
   </DEFINITION>

This is my XSL:

<xsl:template name="DEFINITION" match="DEFINITION">
        
            <xsl:element name="body">
                <xsl:attribute name="break">before</xsl:attribute>
                <xsl:element name="defn">
                    <xsl:attribute name="id" />
                    <xsl:attribute name="scope" />
                    <xsl:value-of select="DEFINEDTERM" />
                </xsl:element>
                <xsl:element name="text">
                    <xsl:value-of select="replace(TEXT[1],'&#x96;','--')" />
                </xsl:element>
            </xsl:element>
            
            <xsl:apply-templates select="*[not(self::TEXT[1])]" />
        
    </xsl:template>

As per my XSL, I want to do something with the DEFINEDTERM element and the TEXT element that immediately follows it.

Then I want to apply-templates to the rest of the elements, except for the DEFINEDTERM and TEXT element that have already been dealt with. Most importantly, I don't want to apply templates to the first TEXT element.

How do I achieve this, because my XSL above does not work.

I have other templates for TEXT and PARAGRAPH, but not DEFINEDTERM. I have <xsl:template match="*|@*" /> at the top of the XSL.



Solution 1:[1]

You did not post the expected result nor a minimal reproducible example, so I can only guess you want to do:

<xsl:template match="DEFINITION">
    <body break="before">
        <defn id="" scope="">
            <xsl:value-of select="DEFINEDTERM" />
        </defn>
        <text>
            <xsl:value-of select="replace(DEFINEDTERM/following-sibling::TEXT[1],'&#150;','--')" />
        </text>
    </body>
    <xsl:apply-templates select="* except (DEFINEDTERM  | DEFINEDTERM/following-sibling::TEXT[1])" />
</xsl:template>

At least that's what I understand as:

I want to do something with the DEFINEDTERM element and the TEXT element that immediately follows it.

This is assuming you are using XSLT 2.0 or higher (otherwise you would not be able to use the replace() function).

--
P.S. You might want to make this a bit more efficient by defining DEFINEDTERM/following-sibling::TEXT[1] as a variable first, then referring to the variable instead.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 michael.hor257k