Reputation: 41
I have started learning XSLT just recently and have come up with a scenario.The source and target structure are exactly the same this am able to accomplish with the code below:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy><xsl:apply-templates select="node()|@*" /></xsl:copy>
</xsl:template>
</xsl:stylesheet>
But my requirement is to create the target node only if one of the conditions is met.
Example if
VNum eq 999
source and target should look like this:
Source
<POExt>
<SD>01</SD>
<PODet>
<PNum schemeAgencyID="TEST">12345678</PNum>
<VNum>999</VNum>
</PODet>
<PODet>
<PNum schemeAgencyID="">45654654</PNum>
<VNum>001</VNum>
</PODet>
</POExt>
Target
<POExt>
<SD>01</SD>
<PODet>
<PNum schemeAgencyID="TEST">12345678</PNum>
<VNum>999</VNum>
</PODet>
</POExt>
<PODet>
is repeated everytime it meets the VNum criteria, if none of the <PODet>
meets the criteria it is OK to have
<POExt>
<SD>01</SD>
</POExt>
Want to accomplish this using Copy and apply-templates, any help would be much appreciated.
Thanks..
Upvotes: 4
Views: 1123
Reputation: 24836
When working with the identity rule you need to override the elements by matching templates.
In your case, you want not to copy the PODet
elements which do not met a certain condition. According to a negative logic, you have just to 'shut up' the nodes that do not match your condition. For instance:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="PODet[not(VNum/text()=999)]"/>
</xsl:stylesheet>
If your VNum
is variable, say an input parameter for your transform, in XSLT 2.0 you can simply do:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:param name="VNum" select="999"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="PODet[not(VNum/text()=$VNum)]"/>
</xsl:stylesheet>
In XSLT 1.0 variables are not allowed in the template match pattern so that you have to include the condition check inside the template. For example, you can apply the templates only to the elements matching your condition:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="VNum" select="999"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="PODet">
<xsl:apply-templates select="VNum[text()=$VNum]"/>
</xsl:template>
<xsl:template match="VNum">
<xsl:copy-of select=".."/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 3