Reputation: 9419
I need to transform a block of XML so that if a node (in this case "User/ShopId") is empty it should fallback to a default value, for example "0".
How can this be accomplished with XSLT?
XSLT 1.0
<xsl:template match="/">
<Objects Version="product-0.0.1">
<xsl:apply-templates select='Users/User'/>
</Objects>
</xsl:template>
<xsl:template match="User">
<User>
<xsl:attribute name="Email"><xsl:value-of select="Email"/></xsl:attribute>
<xsl:attribute name="ShopId"><xsl:value-of select="ShopId"/></xsl:attribute>
<xsl:attribute name="ERPCustomer"><xsl:value-of select="ERPCustomer"/></xsl:attribute>
<xsl:attribute name="DisplayName"><xsl:value-of select="DisplayName"/></xsl:attribute>
</User>
</xsl:template>
For example
<Users>
<User>
<Email>[email protected]</Email>
<ShopId>123123</ShopId>
<ERPCustomer>100</ERPCustomer>
<DisplayName>Username</DisplayName>
</User>
<User>
<Email>[email protected]</Email>
<ShopId></ShopId>
<ERPCustomer>100</ERPCustomer>
<DisplayName>Username</DisplayName>
</User>
<Users>
would be transformed into
<Objects Version="product-0.0.1">
<User Email="[email protected]" ShopId="123123" ERPCustomer="100" DisplayName="Username"></User>
<User Email="[email protected]" ShopId="0" ERPCustomer="100" DisplayName="Username"></User>
</Objects>
Upvotes: 0
Views: 592
Reputation: 5432
You can convert all child elements of "User" to attributes and on choose create their values:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml"/>
<xsl:template match="/">
<Objects Version="product-0.0.1">
<xsl:apply-templates select='Users/User'/>
</Objects>
</xsl:template>
<xsl:template match="User">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="User/*">
<xsl:attribute name="{local-name(.)}">
<xsl:choose>
<xsl:when test=". != ''">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Reputation: 167401
Within your code sample you could change
<xsl:attribute name="ShopId"><xsl:value-of select="ShopId"/></xsl:attribute>
to
<xsl:attribute name="ShopId">
<xsl:choose>
<xsl:when test="not(normalize-space(ShopId))">0</xsl:when>
<xsl:otherwise><xsl:value-of select="ShopId"/></xsl:otherwise>
</xsl:choose>
</xsl:attribute>
I would consider changing the approach to template matching and write a template
<xsl:template match="Users/User/ShopId[not(normalize-space())]">
<xsl:attribute name="{name()}">0</xsl:attribute>
</xsl:template>
for that special case and preceed that with
<xsl:template match="Users/User/*">
<xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
to handle the other transformations.
Upvotes: 3