Good day .... I am trying to duplicate nodes with updated/new element text and/or attribute values.
My input XML file:
<?xml version="1.0"?>
<products author="Jesper">
<product id="p1">
<name>Delta</name>
<price>800</price>
<stock>4</stock>
<country>Denmark</country>
</product>
</products>
The desired XML output:
<?xml version="1.0" encoding="utf-8"?>
<products author="Jesper">
<product id="p1">
<name>Delta</name>
<price>800</price>
<stock>4</stock>
<country>Denmark</country>
</product>
<product id="NEW_p1">
<name>NEW_Delta</name>
<price>NEW_800</price>
<stock>NEW_4</stock>
<country>NEW_Denmark</country>
</product>
</products>
After some time, the XSLT that I currently have is as follows:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match ="product">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<product>
<xsl:attribute name ="id">
<xsl:value-of select ="concat('NEW_',@id"/>
</xsl:attribute>
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</product>
</xsl:template>
However, using the above transform, I get the following XML output:
<?xml version="1.0" encoding="utf-8"?>
<products author="Jesper">
<product id="p1">
<name>Delta</name>
<price>800</price>
<stock>4</stock>
<country>Denmark</country>
</product>
<product id="NEW_p1"><product>
<name>Delta</name>
<price>800</price>
<stock>4</stock>
<country>Denmark</country>
</product></product>
</products>
As you can see, the product element is added whilst I declared a new product element with new @id value. Since I use to process child nodes I believe this processes the product element again.
Also, I need help in updating the child node's values (prepending 'NEW_' to each value). Searching the vast questions on this site, I believe I need a template like so:
<xsl:template match="*">
<xsl:element name ="{local-name()}">
<!--for all attributes-->
<xsl:copy-of select ="@*"/>
<xsl:value-of select = "."/>
</xsl:element>
</xsl:template>
Thank you in advance for any suggestions/ideas with my issue.
UPDATED Thank you @Mathias for your answer to my initial question. The answer provided brought one more question involving recursion to deeper levels of an XML structure.
Input XML file:
<products author="Jesper">
<product id="p1">
<name>Delta
<innerName>MiddleDelta
<baseName>FinalDelta</baseName>
</innerName>
</name>
<price>800</price>
<stock>4</stock>
<country>Denmark
<city>Copenhagen</city>
</country>
</product>
</products>
And the Updated desire output file is as such:
<?xml version="1.0" encoding="utf-8"?>
<products author="Jesper">
<product id="p1">
<name>Delta
<innerName>MiddleDelta
<baseName>FinalDelta</baseName>
</innerName>
</name>
<price>800</price>
<stock>4</stock>
<country>Denmark
<city>Copenhagen</city>
</country>
</product>
<product id="NEW_p1">
<name>NEW_Delta
<innerName>NEW_MiddleDelta
<baseName>NEW_FinalDelta</baseName>
</innerName>
</name>
<price>NEW_800</price>
<stock>NEW_4</stock>
<country>NEW_Denmark
<city>NEW_Copenhagen</city>
</country>
</product>
</products>
I can only guess that using templates would work as seeing each node has varying level child nodes. Thank you in advance for ideas/suggestions in this.