I am trying to concatenate several XML fields into another XML fields using XSL.
I want to take an XML with several elements, some of those elements I want to concatenate together, according to some criteria, and add the newly concatenated string to one of the element.
The concatenation should follow the following pattern:
If all elements are all there: build-Space-Item|Description
If there is no Space data: build-Item|Description
If there is no Item: build-Space|Description
If there is no Space and no Item: build|Description
I am very new to XSLT and stumbling around trying to find the correct syntax to create the logic.
My XML looks like this:
<?xml version='1.0' encoding='UTF-8'?>
<document>
<businessobjects>
<BaseOrder>
<Code>1190.00</Code>
<Item>VE216</Item>
<buil>CORP</buil>
<Space></Space>
<Type>Request</Type>
<Description>Description 1</Description>
</BaseOrder>
<BaseOrder>
<Code>64497.00</Code>
<Item>HP01</Item>
<buil>FO3</buil>
<Space>002</Space>
<Type>PPM</Type>
<Description>Description 2</Description>
</BaseOrder>
<BaseOrder>
<Code>77793.00</Code>
<Item></Item>
<buil>EN4</buil>
<Space>123</Space>
<Type>Request</Type>
<Description>Description 3</Description>
</BaseOrder>
<BaseOrder>
<Code>70796.00</Code>
<Item></Item>
<buil>SHS</buil>
<Space></Space>
<Type>Event</Type>
<Description>Description 4</Description>
</BaseOrder>
</businessobjects>
</document>
My output XML should sendup looking like this:
<?xml version='1.0' encoding='UTF-8'?>
<document>
<businessobjects>
<BaseOrder>
<Code>1190.00</Code>
<Description>CORP-VE216|Description 1</Description>
</BaseOrder>
<BaseOrder>
<Code>64497.00</Code>
<Description>FO3-002-HP01|Description 2</Description>
</BaseOrder>
<BaseOrder>
<Code>77793.00</Code>
<Description>EN4-123|Description 3</Description>
</BaseOrder>
<BaseOrder>
<Code>70796.00</Code>
<Description>SHS|Description 4</Description>
</BaseOrder>
</businessobjects>
</document>
My XSL is only catching on the first case, this might be because of the choose(?). Can anyone give me a lead on how to properly do this?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8" media-type="xml/plain"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!-- drop elements with smart (kinda..) concat-->
<xsl:template match="BaseOrder">
<BaseOrder>
<xsl:variable name="noSpace" select="concat(build,'-',Item,'|')" />
<xsl:variable name="noItem" select="concat(build,'-',Space,'|')" />
<xsl:variable name="noSpaceItem" select="concat(build,'|')" />
<xsl:variable name="full" select="concat(build,'-',Space,'-',Item,'|')" />
<xsl:choose>
<!-- no space -->
<xsl:when test="not(@Space)">
<Code>
<xsl:value-of select="Code"/>
</Code>
<Description>
<xsl:value-of select="concat($noSpace,Description)"/>
</Description>
</xsl:when>
<!-- no Item -->
<xsl:when test="not(@Item)">
<Code>
<xsl:value-of select="Code"/>
</Code>
<Description>
<xsl:value-of select="concat($noItem,Description)"/>
</Description>
</xsl:when>
<!-- no Space or Item -->
<xsl:when test="not(@Space) and not(@Item)">
<Code>
<xsl:value-of select="Code"/>
</Code>
<Description>
<xsl:value-of select="concat($noSpaceItem,Description)"/>
</Description>
</xsl:when>
<!-- When all -->
<xsl:otherwise>
<Code>
<xsl:value-of select="Code"/>
</Code>
<Description>
<xsl:value-of select="concat($full,Description)"/>
</Description>
</xsl:otherwise>
</xsl:choose>
</BaseOrder>
</xsl:template>
</xsl:stylesheet>
Edit: Elements not Attributes..
CodePudding user response:
How about simply:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BaseOrder">
<xsl:copy>
<xsl:copy-of select="Code"/>
<Description>
<xsl:value-of select="buil, Space[text()], Item[text()]" separator="-"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Description"/>
</Description>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Or, if you prefer:
<xsl:template match="BaseOrder">
<xsl:copy>
<xsl:copy-of select="Code"/>
<Description>
<xsl:value-of select="string-join((buil, Space/text(), Item/text()), '-'), Description" separator="|"/>
</Description>
</xsl:copy>
</xsl:template>