I have created an XSLT and i was wondering how it is possible to copy all nodes between one set of tags, and add another tag at the bottom. I have created the XSLT that has all the logic for determining which tag to add, and what it should be called. However the issue i am now getting is that i can not copy all the other tags across too. Below are the files in question:
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/csvImportSchema">
<csvImportSchema>
<xsl:for-each select="payload">
<payload>
<xsl:copy-of select="@*"/>
<xsl:variable name="ean">
<xsl:value-of select="ean"/>
</xsl:variable>
<xsl:for-each select="../product">
<xsl:if test="ean = $ean">
<productId><xsl:value-of select="article"/></productId>
</xsl:if>
</xsl:for-each>
</payload>
</xsl:for-each>
</csvImportSchema>
</xsl:template>
</xsl:stylesheet>
INPUT
<?xml version="1.0" encoding="UTF-8"?>
<csvImportSchema>
<payload>
<test>1</test>
<test2>2</test2>
<test3>3</test3>
<ean>1111111111</ean>
<productId/>
</payload>
<product>
<article>722619</article>
<ean>1111111111</ean>
</product>
</csvImportSchema>
CURRENT OUTPUT
<?xml version="1.0" encoding="utf-8"?>
<csvImportSchema>
<payload>
<productId>722619</productId>
</payload>
</csvImportSchema>
DESIRED OUTPUT
<?xml version="1.0" encoding="UTF-8"?>
<csvImportSchema>
<payload>
<test>1</test>
<test2>2</test2>
<test3>3</test3>
<ean>1111111111</ean>
<productId>722619</productId>
</payload>
</csvImportSchema>
XSLT <xsl:copy-of> The <xsl:copy-of> element creates a copy of the current node. Note: Namespace nodes, child nodes, and attributes of the current node are automatically copied as well! Tip: This element can be used to insert multiple copies of the same node into different places in the output.
The following-sibling axis indicates all the nodes that have the same parent as the context node and appear after the context node in the source document.
Returns the contents of the current group selected by xsl:for-each-group. Available in XSLT 2.0 and later versions. Available in all Saxon editions. current-group() ➔ item()*
This short and simple transformation:
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="productId">
<productId>
<xsl:value-of select="../../product/article"/>
</productId>
</xsl:template>
<xsl:template match="product"/>
</xsl:stylesheet>
when applied on the provided XML document:
<csvImportSchema>
<payload>
<test>1</test>
<test2>2</test2>
<test3>3</test3>
<ean>1111111111</ean>
<productId/>
</payload>
<product>
<article>722619</article>
<ean>1111111111</ean>
</product>
</csvImportSchema>
produces the wanted, correct result:
<csvImportSchema>
<payload>
<test>1</test>
<test2>2</test2>
<test3>3</test3>
<ean>1111111111</ean>
<productId>722619</productId>
</payload>
</csvImportSchema>
Explanation:
The identity rule copies "as-is" every node for which it is selected for execution.
An overriding template matching product
"deletes" this element from the output (by its empty body).
Another overriding template matches productId
and generates this element with a text-node child taken from product/article
.
One observation on your code. Don't use this:
<xsl:variable name="ean">
<xsl:value-of select="../ean"/>
</xsl:variable>
when you could write this:
<xsl:variable name="ean" select="../ean"/>
Not only is it verbose, it's also incredibly inefficient: instead of binding $ean to an existing node, you are extracting the string value of an existing node, forming a text node with that string value, creating a new XML document tree, and adding this text node to the content of this new document. (I once got a stylesheet to run 3 times faster by eliminating this horrible construct.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With