Exclude XML nodes using XSLT

I have very simple XML. I recreate some XML and add some template text to the last XML file to import into InDesign when I am done.

Here's the problem: not all XML fields are used in every record. So, when XSLT adds template text, it appears even in entries that do not include XML elements.

I tried to use select -> when - otherwise to search for the item, then use the if element, or ignore the template pattern and insert NOTHING if the item is not in the record.

Here are some examples of 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 tried to use, but added "Hold Co:" and "Total Assets:" even to entries 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 Select -> When -> Otherwise, to ignore elements, etc., when they are not displayed in the data, but my output shows nothing but the contents of "otherwise".

Any suggestions?

+4
source share
1 answer
 Here 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. 

That's what templates are for - don't use templates in XSLT, how not to use classes in the OO programming language .

This is a simple conversion (note that no conditional statement is used) :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes" /> <xsl:strip-space elements="*"/> <xsl:variable name="vNL" select="'&#xA;'"/> <xsl:template match="/"> <root> <story> <xsl:apply-templates select="root/story/CL"/> </story> </root> </xsl:template> <xsl:template match="CL"> <xsl:apply-templates select="CityDescription"/> <xsl:apply-templates select="BK"/> </xsl:template> <xsl:template match="CityDescription | CompanyName | address"> <xsl:element name="{name()}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> <xsl:template match="BK"> <xsl:value-of select="$vNL"/> <xsl:apply-templates select="CompanyName"/> <xsl:apply-templates select="address"/> <xsl:apply-templates select="HoldingCo"/> <xsl:apply-templates select="TotalAssets"/> <xsl:apply-templates select="TotalLiabilities"/> <xsl:apply-templates select="TotalDeposits"/> <xsl:apply-templates select="EquityCapital"/> </xsl:template> <xsl:template match="HoldingCo"> <HoldingCo> <xsl:text>Holding Co: </xsl:text> <xsl:value-of select="."/> </HoldingCo> </xsl:template> <xsl:template match="TotalAssets"> <TotalAssets> <xsl:text>Total Assets: </xsl:text> <xsl:value-of select="."/> </TotalAssets> </xsl:template> <xsl:template match="TotalLiabilities"> <TotalLiabilities> <xsl:text>Total Liabilities: </xsl:text> <xsl:value-of select="."/> </TotalLiabilities> </xsl:template> <xsl:template match="TotalDeposits"> <TotalDeposits> <xsl:text>Total Deposits: </xsl:text> <xsl:value-of select="."/> </TotalDeposits> </xsl:template> <xsl:template match="EquityCapital"> <EquityCapital> <xsl:text>Total Assets: </xsl:text> <xsl:value-of select="."/> </EquityCapital> </xsl:template> <xsl:template match="text()"/> </xsl:stylesheet> 

when applied to the provided XML document:

 <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> 

creates the desired, correct result:

 <root> <story> <CityDescription>City One</CityDescription> <CompanyName>Corporate Name</CompanyName> <address>123 Main St</address> <HoldingCo>Holding Co: Company Name</HoldingCo> <TotalAssets>Total Assets: 128,319,000</TotalAssets> <TotalLiabilities>Total Liabilities: 117,059,000</TotalLiabilities> <TotalDeposits>Total Deposits: 89,847,000</TotalDeposits> <EquityCapital>Total Assets: 11,260,000</EquityCapital> <CompanyName>Smaller Company</CompanyName> <address>123 Central St</address> <CityDescription>City Two</CityDescription> <CompanyName>Corporate Name Three</CompanyName> <address>123 High St</address> <HoldingCo>Holding Co: Company Name</HoldingCo> <TotalAssets>Total Assets: 128,319,000</TotalAssets> <TotalLiabilities>Total Liabilities: 117,059,000</TotalLiabilities> <TotalDeposits>Total Deposits: 89,847,000</TotalDeposits> <EquityCapital>Total Assets: 11,260,000</EquityCapital> <CompanyName>Smaller Company Four</CompanyName> <address>123 Jones St</address> </story> </root> 

When BK children are processed in document order, the matching pattern can be simplified to:

 <xsl:template match="BK"> <xsl:value-of select="$vNL"/> <xsl:apply-templates/> </xsl:template> 

The same is true to match the CL pattern - it can be replaced with:

 <xsl:template match="CL"> <xsl:apply-templates/> </xsl:template> 

Finally, this template can be completely removed, because it copies the built-in XSLT template that matches any element.

So the conversion after these refactoring is :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes" /> <xsl:strip-space elements="*"/> <xsl:variable name="vNL" select="'&#xA;'"/> <xsl:template match="/"> <root> <story> <xsl:apply-templates select="root/story/CL"/> </story> </root> </xsl:template> <xsl:template match="CityDescription | CompanyName | address"> <xsl:element name="{name()}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> <xsl:template match="BK"> <xsl:value-of select="$vNL"/> <xsl:apply-templates/> </xsl:template> <xsl:template match="HoldingCo"> <HoldingCo> <xsl:text>Holding Co: </xsl:text> <xsl:value-of select="."/> </HoldingCo> </xsl:template> <xsl:template match="TotalAssets"> <TotalAssets> <xsl:text>Total Assets: </xsl:text> <xsl:value-of select="."/> </TotalAssets> </xsl:template> <xsl:template match="TotalLiabilities"> <TotalLiabilities> <xsl:text>Total Liabilities: </xsl:text> <xsl:value-of select="."/> </TotalLiabilities> </xsl:template> <xsl:template match="TotalDeposits"> <TotalDeposits> <xsl:text>Total Deposits: </xsl:text> <xsl:value-of select="."/> </TotalDeposits> </xsl:template> <xsl:template match="EquityCapital"> <EquityCapital> <xsl:text>Total Assets: </xsl:text> <xsl:value-of select="."/> </EquityCapital> </xsl:template> <xsl:template match="text()"/> </xsl:stylesheet> 

Explanation

Instruction:

 <xsl:apply-templates select="someChildName"/> 

only templates are applied (performs processing) if someChildName child node exists.

+4
source

Source: https://habr.com/ru/post/1416086/


All Articles