Search code examples
xmlxsltxslt-1.0transformation

xslt check if child nodes exits with a combination of 2 values


I want to know whether if there are any order nodes with criteria id != -1 and status = Active or Done. See below inputs and outputs for details

Example 1

<order-request>
 <orders>
    <order>
      <name>John</name>
      <id>1</id>
      <status>Done</id>
    </order>
    <order>
      <name>Smith</name>
      <id>-1</id>
      <status>Pending</id>
    </order>
 </orders>
</order-request>

OUTPUT for above xml should be

<orders-list>
 <order>
      <name>John</name>
      <id>1</id>
      <status>Done</id>
 </order>
</orders-list>

Example 2

<order-request>
 <orders>
    <order>
      <name>John</name>
      <id>-1</id>
      <status>Done</id>
    </order>
    <order>
      <name>Smith</name>
      <id>456</id>
      <status>Pending</id>
    </order>
 </orders>
</order-request>

OUTPUT
I should get empty response from xslt( I should not get the <orders-list> tag also) because there is no order node matching id != -1 and status is Active or Done

My xslt is failing with the Example 2 input
For Example 2 I am getting output as <orders-list> </order-list> I should get empty response. I don't want <order-list> tag with no child.

<xsl:stylesheet>
 <xsl:template match="order-request">
        <xsl:if
            test="(orders/order/id[.!= -1]) and ((orders/order/status[.='Active']) or 
 orders/order/status[.='Done']))">
                    <orders-list>
                        <xsl:apply-templates
                            select="order"></xsl:apply-templates>
                    </orders-list>
            </xsl:if>
    </xsl:template>

   <xsl:template match="order">
     <xsl:if test="(id != -1) and (status ='Active' or status ='Done')">
        <order>
          <name><xsl:value-of select="name" /></name>
          <id><xsl:value-of select="id" /></id>
          <status><xsl:value-of select="status'" /></status>
        </order>
     </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Solution

  • For Example 2 I am getting output as <orders-list> </order-list>

    All I am getting with your code is multiple errors. For example:

    <status><xsl:value-of select="status'" /></id>
    

    is not well-formed XML.

    How about something simple:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/order-request">
        <xsl:variable name="eligible-orders" select="orders/order[id=1 and (status ='Active' or status ='Done')]" />
        <xsl:if test="$eligible-orders">
            <orders-list>
                <xsl:copy-of select="$eligible-orders"/>
            </orders-list> 
        </xsl:if>
    </xsl:template>
    
    </xsl:stylesheet>