Reputation: 3111
I have the following XSL file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/EMPLOYEE">
<ROOT>
<xsl:for-each select="ADDRESSES">
<xsl:variable name="ADDRESSES" select="." />
<xsl:for-each select="RENTED_FLATS">
<xsl:variable name="RENTED_FLATS" select="." />
<xsl:element name="RENT_DATA">
<xsl:element name="ADDRESS">
<xsl:value-of select="$ADDRESSES/LINE1" />
</xsl:element>
<xsl:element name="FLOOR">
<xsl:value-of select="$RENTED_FLATS/FLOOR" />
</xsl:element>
</xsl:element>
</xsl:for-each>
</ROOT>
</xsl:template>
</xsl:stylesheet>
The logic is simple: given an input file of ADDRESSES, I want to get the Renting data of each address.
The problem with my implementation is that if there are no nodes "RENTED_FLATS" then it won't enter inside the loop, but I require that, if there's an address without RENTED_FLATS, it still must appear in the output with the element FLOOR empty.
How can I achieve that in XSL?
Thanks and kind regards
Upvotes: 0
Views: 395
Reputation: 122414
I would approach this by replacing the uses of for-each
with apply-templates
, and defining different templates for those ADDRESS
elements that do have RENTED_FLATS
and those those that don't.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/EMPLOYEE">
<ROOT>
<xsl:apply-templates select="ADDRESSES"/>
</ROOT>
</xsl:template>
<xsl:template match="ADDRESSES[RENTED_FLATS]">
<xsl:apply-templates select="RENTED_FLATS"/>
</xsl:template>
<!-- template for addresses that don't match the more specific one above -->
<xsl:template match="ADDRESSES">
<RENT_DATA>
<ADDRESS><xsl:value-of select="LINE1" /></ADDRESS>
<FLOOR/>
</RENT_DATA>
</xsl:template>
<xsl:template match="RENTED_FLATS">
<RENT_DATA>
<ADDRESS><xsl:value-of select="../LINE1" /></ADDRESS>
<FLOOR><xsl:value-of select="FLOOR" /></FLOOR>
</RENT_DATA>
</xsl:template>
</xsl:stylesheet>
Also notice that I've used literal result elements instead of xsl:element
in the cases where the element name is fixed - you only need xsl:element
when the name has to be calculated dynamically.
Upvotes: 1