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.
You might want to adjust the default logic as Stuart suggests, but the main problem is that the height
variable scope must be corrected:
<?xml version="1.0" encoding="UTF-8"?>
<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:value-of select="'0'"/>
</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>
After making the above changes, this input XML:
<?xml version="1.0" encoding="UTF-8"?>
<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>
Will transform to this output XML:
<?xml version="1.0" encoding="UTF-8"?>
<CatalogItem>
<RelationshipData>
<Relationship>
<RelationType>PAGEDETAILSINFO</RelationType>
<RelatedItems count="2">
<RelatedItem referenceKey="Food_And_Bev_Allergen_MVL-1000909090-30"/>
<RelatedItem referenceKey="Food_And_Bev_Allergen_MVL-1000909090-0"/>
</RelatedItems>
</Relationship>
</RelationshipData>
</CatalogItem>
Note that the following is a more natural expression of the default logic:
<xsl:variable name="height">
<xsl:choose>
<xsl:when test="attr[@name = 'pageheight']">
<xsl:value-of select="attr[@name='pageheight']"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Or, if you're using XSLT 2.0, you can use the sequence idiom for default values very concisely:
<xsl:variable name="height"
select="(attr[@name='pageheight'], 0)[1]"/>