Saturday, December 31, 2011

Testing for Empty Elements in XSLT & Xquery


While processing an XML with XSLT sometimes you need to access a node but you want to make sure that that node exists otherwise the XSLT processor will complain (analogous to the infamous null point exception in Java).

For example using this XML:

<Projects>
<Project>
<ProjectName> Teach my toddler computer </ProjectName>
<ProjectActivities>
<ProjectActivity>
<ActivityName> Install Qimo Linux </ActivityName>
</ProjectActivity>
<ProjectActivity>
<ActivityName> Teach mouse game for mouse training </ActivityName >
</ProjectActivity>
</ProjectActivities>
</Project>

<Project>
<ProjectName> Teach my kids piano </ProjectName>
<ProjectActivities/>
</Project>

<Projects>

Suppose you want to iterate over ProjectActivity within project, but some project has no ProjectActivity (such as the "Teach my kids piano" project above).

XSLT solution
* To test if the element exists in XSLT you can use: xsl:if test="ProjectActivities/ProjectActivity".
*
To test if the element exists and non-empty: xsl:if test="string(ProjectActivities/ProjectActivity)".
*To test that the element exists and has text or any element content (e.g. subnodes or attributes): xsl:if test=" ProjectActivities/ProjectActivity/text() or ProjectActivities/ProjectActivity/*"

So for example using this test in this XSL:

<xsl:for-each select="//Projects/Project">
<xsl:variable name="nuproj" select="ProjectName"/>
Project:<xsl:value-of select="ActivityName"/>
<xsl:if test="ProjectActivities/ProjectActivity">
<xsl:for-each select="ProjectActivities/ProjectActivity">
To do:<xsl:value-of select="ActivityName"/>
<xsl:text></xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text></xsl:text>
</xsl:for-each>

you will expect this result:

Project: Teach my toddler computer
To do: Install Qimo Linux
Project: Teach my kids piano

Xquery solution:
* To test if the element exists :exists($ProjectVariable/ProjectActivities/ProjectActivity)
or using similar strategy used by xslt above:
if ($ProjectVariable/ProjectActivities/ProjectActivity) then ... else ...

*To test if the string non-empty:string-length($ProjectVariable/ProjectActivities/ProjectActivity) != 0)
or using similar strategy used by xslt above:
if (string($ProjectVariable/ProjectActivities/ProjectActivity)!="") then ... else ...

Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




References:
XSLT Empty Element tutorial

Beginning XSLT and XPath: by Ian Williams

1 comment:

Sandeep said...

Thanks . This post helped me