I have some very simple XML. I am recreating some XML and adding some boilerplate text into the final XML file to import into InDesign when I’m done.
Here’s the problem: not all XML fields are being used in every record. So, when the XSLT adds the boilerplate text it appears even in the records that don’t include the XML elements.
I tried using the choose >> when >> otherwise to look for the element, then use the element if is there, or ignore the boilerplate and insert NOTHING if the element is not in the record.
Here is some sample XML data:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<story>
<CL>
<CityDescription>City One</CityDescription>
<BK>
<CompanyName>Corporate Name</CompanyName>
<address>123 Main St</address>
<HoldingCo>Company Name</HoldingCo>
<TotalAssets>128,319,000</TotalAssets>
<TotalLiabilities>117,059,000</TotalLiabilities>
<TotalDeposits>89,847,000</TotalDeposits>
<EquityCapital>11,260,000</EquityCapital>
</BK>
<BK>
<CompanyName>Smaller Company</CompanyName>
<address>123 Central St</address>
</BK>
</CL>
<CL>
<CityDescription>City Two</CityDescription>
<BK>
<CompanyName>Corporate Name Three</CompanyName>
<address>123 High St</address>
<HoldingCo>Company Name</HoldingCo>
<TotalAssets>128,319,000</TotalAssets>
<TotalLiabilities>117,059,000</TotalLiabilities>
<TotalDeposits>89,847,000</TotalDeposits>
<EquityCapital>11,260,000</EquityCapital>
</BK>
<BK>
<CompanyName>Smaller Company Four</CompanyName>
<address>123 Jones St</address>
</BK>
</CL>
</story>
</root>
Here is the XSLT that I was trying to use, but it added “Holding Co:” and “Total Assets:” even to the records that did not contain elements:
<?xml version="1.0" encoding="UTF-8"?><!-- DWXMLSource="Testing.xml" -->
<!DOCTYPE xsl:stylesheet [
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="XML" />
<xsl:template match="/">
<root>
<story>
<xsl:for-each select="root/story/CL">
<CityDescription><xsl:value-of select="CityDescription"/></CityDescription><xsl:text>
</xsl:text>
<xsl:for-each select="BK">
<CompanyName><xsl:value-of select="CompanyName"/></CompanyName><xsl:text>
</xsl:text>
<address><xsl:value-of select="address"/></address><xsl:text>
</xsl:text>
<HoldingCo><xsl:text>Holding Co: </xsl:text><xsl:value-of select="HoldingCo"/></HoldingCo><xsl:text>
</xsl:text>
<TotalAssets><xsl:text>Total Assets: </xsl:text><xsl:value-of select="TotalAssets"/></TotalAssets><xsl:text>
</xsl:text>
<TotalLiabilities><xsl:text>Total Liabilities: </xsl:text><xsl:value-of select="TotalLiabilities"/></TotalLiabilities><xsl:text>
</xsl:text>
<TotalDeposits><xsl:text>Total Deposits: </xsl:text><xsl:value-of select="TotalDeposits"/></TotalDeposits><xsl:text>
</xsl:text>
<EquityCapital><xsl:text>Total Assets: </xsl:text><xsl:value-of select="EquityCapital"/></EquityCapital><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</story>
</root>
</xsl:template>
</xsl:stylesheet>
I tried using Choose >> When >> Otherwise to basically ignore the elements , et al when they do not appear in the data, but my output show nothing but the “otherwise” content.
Any suggestions?
This is what templates are for — not using templates in XSLT is like not using classes in an OO programming language.
This simple transformation (notice that not a single conditional instruction has been used):
when applied on the provided XML document:
produces the wanted, correct result:
As the child elements of
BKare processed in document order, the matching template can be simplified to just:The same is valid for the template matching
CL— it can be replaced by:Finally, this template can be completely removed, because it copies exactly the XSLT built-in template that matches any element.
Thus, the transformation after these refactorings is:
Explanation:
The instruction:
only applies templates (performs processing) if a
someChildNamechild node exists.