qubiter
qubiter

Reputation: 245

how to use greater than function in XSLT for a tag occurrence

I have an XSLT which looks like this:

<xsl:if test="PARENT_TAG[1]">
do somthing
</xsl:if>

now i want to also do something else for all occurrences of PARENT_TAG greater than one i.e. for example: PARENT_TAG[2], PARENT_TAG[3], PARENT_TAG[4], PARENT_TAG[5]......... PARENT_TAG[100]

May be like this:

<xsl:if test="PARENT_TAG[2-100]"> <!--need some logic here to capture all the parent_tags greater than "1"-->
do something different
</xsl:if>

How can i apply this logic in the XSLT? please help! Both these if conditions will be within the top level logic sharing sibling relation. like this:

<xsl: for-each select="HIGHLEVEL_TAG">    
    <xsl:if test="PARENT_TAG[1]">
      do somthing
    </xsl:if>
    <xsl:if test="PARENT_TAG[2-100]"> <!--need some logic here to capture all the parent_tags greater than "1"-->
      do something different
    </xsl:if>
</xsl:for-each>

Upvotes: 1

Views: 4013

Answers (2)

Michael Kay
Michael Kay

Reputation: 163352

Everyone answering this question seems to be reading your requirements in a different way, which suggests there is a problem with clarity in your question.

You start by saying "I have an XSLT which looks like this" but you don't tell us what it's intended to do, and since it might well be wrong, we can't infer the requirements from the code.

You then say "now i want to also do something else for all occurrences of PARENT_TAG greater than one". This suggests to me that the first bit of code was intended to process the first PARENT_TAG only.

If my interpretation is correct then you probably want:

<xsl:for-each select="PARENT_TAG">
  <xsl:choose>
    <xsl:when test="position()=1"> do something </xsl:when>
    <xsl:otherwise> do something else </xsl:otherwise>
  </xsl:choose>
</xsl:for-each>

If you're not used to writing specifications in unambiguous legalese prose, then a good way to communicate your requirements is often with an example: show us a typical input and the desired output.

Upvotes: 0

Tomalak
Tomalak

Reputation: 338248

XSLT is XML itself. It must obey the syntax rules of XML. < and > are valid operators in XPath, but if you use them in XML then they must be XML-escaped.

<xsl:if test="$foo &gt; 1"> <!-- translates to '$foo > 1' during parsing of the XSLT document -->

It seems you want to decide what to do based on the number of <PARENT_TAG> elements. So let's count them.

<xsl:for-each select="HIGHLEVEL_TAG">
  <xsl:if test="count(PARENT_TAG) = 1">
    do something
  </xsl:if>
  <xsl:if test="count(PARENT_TAG) &gt; 1">
    do something different
  </xsl:if>
</xsl:for-each>

Now if you really want to do one thing when there is only one <PARENT_TAG> and something different when there is more than one, then this won't work. There's always at least one, which means the first <xsl:if> will always run. There are several ways to solve this:

  1. You could modify the first <xsl:if> condition to explicitly exclude the case where there is more than one <PARENT_TAG>.

  2. Better would be an <xsl:choose> instead of an <xsl:if> - make sure you test for the "more than one" case first.

    <xsl:for-each select="HIGHLEVEL_TAG">
      <xsl:choose>
        <xsl:if test="count(PARENT_TAG) &gt; 1">
          do something different
        </xsl:if>
        <xsl:if test="count(PARENT_TAG) = 1">
          do something
        </xsl:if>
      </xsl:choose>
    </xsl:for-each>
    
  3. But actually the idiomatic way of dealing with this is to use templates - one for the specific case (there is more than one <PARENT_TAG>), and a generic one that matches all the other cases (0 or 1 <PARENT_TAG>):

    <xsl:template match="HIGHLEVEL_TAG[count(PARENT_TAG) &gt; 1]">
      do something different
    </xsl:template>
    
    <xsl:template match="HIGHLEVEL_TAG">
      do something
    </xsl:template>
    

Now you can drop the <xsl:for-each> and call:

<xsl:apply-templates select="HIGHLEVEL_TAG" />

and the XSLT processor will sort it out for you.

If you are unsure how <xsl:apply-templates> works, take a look at What are the differences between 'call-template' and 'apply-templates' in XSL?.


The same approach also works for the "I want to do something else for all occurrences of <PARENT_TAG> greater than one" case, the only difference is that we use position() instead of count() to decide which template should run:

<xsl:template match="PARENT_TAG[position() &gt; 1]">
  do something different
</xsl:template>

<xsl:template match="PARENT_TAG">
  do something
</xsl:template>

and

<xsl:apply-templates select="PARENT_TAG" />

Upvotes: 2

Related Questions