2

XML:

<Root>
  <Elements>
    <Element>el1</Element>
    <Element>el2</Element>
   </Elements>

  <Elements>
    <Element>el1</Element>
    <Element>el2</Element>
   </Elements>
</Root>

Trying to generate to apply two different templates for the same element.

Main template:

<xsl:stylesheet version="1.0">
      <xsl:template match="/Root">
           At root level
             <xsl:apply-templates select="Elements">

             <h1>Render something more</h1>

             <xsl:apply-templates select="Elements" mode="1:Custom">
        </xsl:template>


    <!-- This doesn't render though it is called above-->
      <xsl:template match="Elements"> 
      render something here
      </xsl:template>

    <!-- This renders twice -->
      <xsl:template match="Elements" mode="1:Custom">
      render something else here
      </xsl:template>
</xsl:stylesheet>

If I add mode to the first template, both don't render.

Also tried:

 <xsl:apply-templates select="Elements" mode="1:Custom" />

with the different template to apply as:

<xsl:apply-templates select="Elements" mode="Different" />

Only one of the two(the first one which has the mode specified is rendered). i.e

<xsl:template match="Elements">
</xsl:template>

doesn't render

or <xsl:template match="Elements" mode="Different" />renders twice.

How should I fix this? Everywhere I researched, it suggests to put a priority on the mode. Must be something simple since so many programmers use it?

Loser Coder
  • 2,338
  • 8
  • 42
  • 66
  • 2
    This cannot be answered without seeing the rest of your XSLT program. You have a pretty simple mistake somewhere, but the context is not enough to point it out. Try to generate the smallest possible XSLT/XML pair that still fails for you and add it to your question. – Tomalak Jun 10 '11 at 15:50
  • What you have described is lecit and should work. You should show us a bit more of the XSLT involved. – Emiliano Poggi Jun 10 '11 at 15:56
  • I have now edited my question. Hope it is a little clearer? – Loser Coder Jun 10 '11 at 16:23
  • Did you try without any prefix for any modes? Meaning without "1:" or anything with : in it. – Cristian Vat Jun 10 '11 at 16:30
  • Good question, +1. See my answer for an explanation of the problem you are having and for a complete, short and easy solution :) – Dimitre Novatchev Jun 11 '11 at 03:32
  • Dear @LoserCoder, Instead of answering your own question with completely different code, and accepting your own, unrelated answer, you should have looked at the answer and suggestions that directly address and fix the problem in the provided code! Really not good! – Dimitre Novatchev Sep 04 '21 at 16:46

2 Answers2

5
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:template match="/Root">
           At root level
             <xsl:apply-templates select="Elements"/>

             <h1>After first template</h1>

             <xsl:apply-templates select="Elements" mode="Custom"/>
        </xsl:template>

      <xsl:template match="Elements">
      <p>First template</p> 
          <xsl:apply-templates select="Element"/>
      </xsl:template>

      <xsl:template match="Elements" mode="Custom">
         <p>Second template      </p>
      </xsl:template>
      </xsl:stylesheet>
Loser Coder
  • 2,338
  • 8
  • 42
  • 66
5
<xsl:template match="Elements" mode="1:Custom">

You are using syntactically illegal mode name here (must be a QName) and any compliant XSLT processor must issue an error.

Solution: Just change

    mode="1:Custom"

to

    mode="Custom"

Therefore, this transformation is correct:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/Root">
       At root level
     <xsl:apply-templates select="Elements"/>
     <h1>Render something more</h1>

     <xsl:apply-templates select="Elements" mode="Custom"/>
    </xsl:template>

    <xsl:template match="Elements">
       render something here

    </xsl:template>

    <xsl:template match="Elements" mode="Custom">

     render something else here
   </xsl:template>

   <xsl:template match="text()"/>
</xsl:stylesheet>

when applied on the provided XML document:

<Root>
    <Elements>
        <Element>el1</Element>
        <Element>el2</Element>
    </Elements>
    <Elements>
        <Element>el1</Element>
        <Element>el2</Element>
    </Elements>
</Root>

the wanted, correct result is produced:

       At root level

   render something here


   render something here

<h1>Render something more</h1>

 render something else here


 render something else here
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431