XSLT condition to check if node exists

Victor picture Victor · Dec 22, 2014 · Viewed 8.9k times · Source

I have below sample XML in which I want to check if the node exist.

Sample XML is

<document>
<item>
    <ID>1000909090</ID>
    <flex>
        <attrGroupMany name="pageinfo">
            <row>
                <attr name="pagelength">10</attr>
                <attr name="pagewidth">20</attr>
                <attr name="pageheight">30</attr>
            </row>
            <row>
                <attr name="pagelength">10</attr>
                <attr name="pagewidth">20</attr>
            </row>
        </attrGroupMany>
    </flex>
</item>
</document>

I am using below XSLT but is not getting converted

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="document">
    <CatalogItem>
        <RelationshipData>
            <xsl:for-each select="item">
                <Relationship>
                    <RelationType>PAGEDETAILSINFO</RelationType>
                    <RelatedItems>
                        <xsl:attribute name="count">
                            <xsl:value-of select="count(flex//attrGroupMany[@name = 'pageinfo']/row)"/>
                        </xsl:attribute>
                        <xsl:for-each select="flex//attrGroupMany[@name = 'pageinfo']/row">
                            <xsl:choose>
                                <xsl:when test="not(string-length(attr[@name = 'pageheight'] )) = 0">
                                    <xsl:variable name="height" select="attr[@name='pageheight']"/>
                                </xsl:when>                                                         
                                <xsl:otherwise>
                                    <xsl:variable name="height" select="'0'"/>
                                </xsl:otherwise>
                            </xsl:choose> 
                            <RelatedItem>
                                <xsl:attribute name="referenceKey">
                                    <xsl:value-of select="concat('Food_And_Bev_Allergen_MVL','-',ancestor::item/ID,'-',$height)"/>
                                </xsl:attribute>
                            </RelatedItem>
                        </xsl:for-each>
                    </RelatedItems>
                </Relationship>
            </xsl:for-each>
        </RelationshipData>
    </CatalogItem>
</xsl:template>
</xsl:stylesheet>

I think the choose condition is incorrect. can you please let me know what will be the correct condition.

Answer

StuartLC picture StuartLC · Dec 22, 2014

To determine whether the attribute is present or not, simply use not() when the element is current.

I would reverse the logic, viz move the not present first:

<xsl:when test="not(attr[@name='pageheight'])">
  ... not present, default it 

Will detect if the row has no attr elements with a @name attribute.

Edit

You can't assign <xsl:variable> in a branch like that - it will go out of scope within the xsl:choose. Switch to:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="document">
    <CatalogItem>
      <RelationshipData>
        <xsl:for-each select="item">
          <Relationship>
            <RelationType>PAGEDETAILSINFO</RelationType>
            <RelatedItems>
              <xsl:attribute name="count">
                <xsl:value-of select="count(flex//attrGroupMany[@name = 'pageinfo']/row)"/>
              </xsl:attribute>
              <xsl:for-each select="flex//attrGroupMany[@name = 'pageinfo']/row">
                <xsl:variable name="height">
                  <xsl:choose>
                    <xsl:when test="not(attr[@name = 'pageheight'])">
                      <xsl:text>0</xsl:text>
                    </xsl:when>
                    <xsl:otherwise>
                      <xsl:value-of select="attr[@name='pageheight']"/>
                    </xsl:otherwise>
                  </xsl:choose>
                </xsl:variable>
                <RelatedItem>
                  <xsl:attribute name="referenceKey">
                    <xsl:value-of select="concat('Food_And_Bev_Allergen_MVL','-',ancestor::item/ID,'-',$height)"/>
                  </xsl:attribute>
                </RelatedItem>
              </xsl:for-each>
            </RelatedItems>
          </Relationship>
        </xsl:for-each>
      </RelationshipData>
    </CatalogItem>
  </xsl:template>
</xsl:stylesheet>

And the returned snippet includes:

  <RelatedItems count="2">
    <RelatedItem referenceKey="Food_And_Bev_Allergen_MVL-1000909090-30" />
    <RelatedItem referenceKey="Food_And_Bev_Allergen_MVL-1000909090-0" />
  </RelatedItems>