Ksthawma
Ksthawma

Reputation: 1285

How to conditionally output tags?

Tags can be outputted by either directly typing

  <div>
    <span>complex...</span>
  </div>

or using <xsl:element>,

  <xsl:element name="div">
    <span>complex...</span>
  </xsl:element>

My question is how to do this: when x, output <div>, when y, output <a>, when z, output no tag?

One of course can make three templates, or even write ugly code as

<xsl:when ...x >
    <![CDATA[ <div>  ]]> 
</xsl:when>

<span>complex...</span>

<xsl:when ...x >
    <![CDATA[ </div>  ]]> 
</xsl:when>

but is there a way to conditionally provide the value of the name attribute of xsl:element?

I tried this, failed:

<xsl:variable name="a" select="'div'"/>
<xsl:element name="$a">
...

[edited] Forgot to say, XSLT1.0 only

Upvotes: 2

Views: 3230

Answers (3)

michael.hor257k
michael.hor257k

Reputation: 117043

Here's another way to look at it:

<xsl:variable name="content">
    <span>complex...</span>
</xsl:variable>

<xsl:choose>
    <xsl:when ... x>
        <div>
            <xsl:copy-of select="$content"/>
        </div>
    </xsl:when>
    <xsl:when ... y>
        <a>
            <xsl:copy-of select="$content"/>
        </a>
    </xsl:when>
    <xsl:when ... z>
        <xsl:copy-of select="$content"/>
    </xsl:when>
</xsl:choose>

Upvotes: 2

Michael Kay
Michael Kay

Reputation: 163418

XSLT doesn't output tags: it outputs nodes to a result tree. Your suggestion of using constructs like <![CDATA[ </div> ]]> is therefore way off the mark: you can't add half a node to a tree.

However, there's no difficulty with conditional generation of elements nodes. If you want to create an element but compute its name conditionally, then in XSLT 2.0 you can do

<xsl:element name="{if (test) then 'a' else 'b'}">

or if you're stuck with 1.0, the much more verbose

<xsl:variable name="elname">
  <xsl:choose>
    <xsl:when test="test">a</xsl:when>
    <xsl:otherwise>b</xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:element name="{$elname}"/>

If you want to output an element or nothing depending on a condition, just do

<xsl:if test="test2">
  <e/>
</xsl:if>

Upvotes: 0

Marcus Rickert
Marcus Rickert

Reputation: 4238

The name attribute is not expecting a full-fledge XPath expression but simply a string. So, instead of using name="$a" you only have to evaluate the Xpath expression into a string by bracing it with curly braces:

<xsl:element name="{$a}">

As for the conditional creation of the surrounding tag you could do something like this:

<xsl:variable name="tag_name">
  <xsl:choose>
    <xsl:when test="x">
      <xsl:text>div</xsl:text>
    </xsl:when>
    <xsl:when test="y">
      <xsl:text>a</xsl:text>
    </xsl:when>
  </xsl:choose>

  <!-- possibly other checks for different tag names -->

<xsl:variable>

<xsl:choose>
  <xsl:when test="$tag_name != ''">
     <xsl:element name="$tag_name">

       <!-- whatever has to be put into a tagged block (A) -->

     </xsl:element>
  </xsl:when>

  <xsl:otherwise>

     <!-- whatever has to be put into a untagged block (B) -->

  </xsl:otherwise>

</xsl:choose>

If A and B are equal you could put that into a template.

Upvotes: 1

Related Questions