Omitting Empty Elements and Attributes

If you look back to HierarchyToFlat.xml, the desired result file for one of the examples above, you'll notice that ShipToStreet2 and ShipToCountry are empty Elements. This may be okay for some applications and schemas, but it may not be for others. These were created because in our xsl:template content we had as a literal result the start and end tags for these Elements, and the select for the xsl:value-of didn't find a match in the source tree. We can tell if we might run into a situation like this by either knowing the business data or reviewing the schema for the source document. If there's a minOccurs of zero on an Element in a sequence, then you should code to avoid creating empty Elements if you can't handle them in your result document.

There is a fairly simple technique for making sure that we don't create such empty Elements. Let's take a simple case of converting a buyer's name and address from one format to another. There may or may not be a BuyerStreet2 Element. We want the result tree to contain a Street2 Element if there is a BuyerStreet2 Element in the source but not to create one if there isn't. The source tree fragment appears below.

Source (MissingElement.xml)
<?xml version="1.0" encoding="UTF-8"?>
<MissingElement>
  <BuyerName>My Name</BuyerName>
  <BuyerStreet1>My Street</BuyerStreet1>
  <BuyerCity>My City</BuyerCity>
  <BuyerState>TX</BuyerState>
  <BuyerZip>99999</BuyerZip>
</MissingElement>

We want the result to look like the following file, with no empty Street2 Element.

Result (NoEmpties.xml)
<?xml version="1.0" encoding="UTF-8"?>
<NoEmpties>
  <Name>My Name</Name>
  <Street1>My Street</Street1>
  <City>My City</City>
  <State>TX</State>
  <Zip>99999</Zip>
</NoEmpties>

Here's the stylesheet.

Stylesheet (NoEmpties.xsl)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8"
      indent="yes"/>
  <xsl:template match="/MissingElement">
    <NoEmpties>
      <Name>
        <xsl:value-of select="BuyerName"/>
      </Name>
      <Street1>
        <xsl:value-of select="BuyerStreet1"/>
      </Street1>
      <xsl:if test="BuyerStreet2">
        <Street2>
          <xsl:value-of select="BuyerStreet2"/>
        </Street2>
      </xsl:if>
      <City>
        <xsl:value-of select="BuyerCity"/>
      </City>
      <State>
        <xsl:value-of select="BuyerState"/>
      </State>
      <Zip>
        <xsl:value-of select="BuyerZip"/>
      </Zip>
    </NoEmpties>
  </xsl:template>
</xsl:stylesheet>

XSLT is so flexible that there are other ways to handle this, but this method is pretty simple and straightforward. All we need to do is to put the literals for the Street2 start and end tags and the associated xsl:value-of into an xsl:if. The expression in the select simply has the name of the source Element. The expression evaluates to true if the Element is present and false if it isn't.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset