user634545
user634545

Reputation: 9419

Default value for empty node

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

Answers (2)

Linga Murthy C S
Linga Murthy C S

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

Martin Honnen
Martin Honnen

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

Related Questions