Im new to xsltproc and want to transform this XML:
<services>
<event name="Something.zip">
<enabled>true</enabled>
<bindings>
<binding name="Example">
<machine>example-name</machine>
<product>
<type>Shared</type>
<version>1.0</version>
<location>/path/to/something</location>
</product>
</binding>
</bindings>
</event>
</services>
To this one:
<services>
<event name="Something.zip">
<enabled>true</enabled>
<bindings>
<binding name="Example">
<machine>example-name</machine>
<product>
<type>Shared</type>
<version>1.0</version>
<location>/path/to/something</location>
</product>
</binding>
<binding name="Example-1">
<machine>example-name-test</machine>
<product>
<type>Shared</type>
<version>1.0</version>
<location>/path/to/something</location>
</product>
</binding>
</bindings>
</event>
</services>
Those are the points that I should follow:
The insert.xsl that I wrote:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://some/xml/namespace" xmlns:tc="http://some/xml/namespace" exclude-result-prefixes="tc">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tc:binding">
<xsl:copy-of select="."/>
<binding name="{@name}-1">
<xsl:copy-of select="*"/>
</binding>
</xsl:template>
</xsl:stylesheet>
With help from y.arazim I have duplicated the binding inside the bindings and change the name attribute as suggested. Yet, cant solve how to change the in the new Example-1 binding block.
P.S, if I have tag value with blank spaces, will the xsltproc remove those whitespaces and leave a closed tag instead? If yes, is there an option to avoid this behavior?
Working Stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://some/xml/namespace" xmlns:tc="http://some/xml/namespace" exclude-result-prefixes="tc">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tc:binding">
<xsl:copy-of select="."/>
<binding name="{@name}-1">
<machine>
<xsl:value-of select="concat(tc:machine, '-test')"/>
</machine>
<xsl:copy-of select="*[not(self::tc:machine)]"/>
</binding>
</xsl:template>
</xsl:stylesheet>
After long hauling, the final solution(based on y.arazim answer) was to retrieve the xml elements from the referred namespace by adding the prefix before the element.
For some reason it does nothing.
That's not true. It does something: it throws an error:
Cannot add attributes to an element if children have been already added to the element.
To get the result you show, try something like:
<xsl:template match="binding">
<xsl:copy-of select="."/>
<binding name="{@name}-1">
<machine>
<xsl:value-of select="concat(machine, '-test')"/>
</machine>
<xsl:copy-of select="product"/>
</binding>
</xsl:template>
Do note that your stylesheet declares a default namespace xmlns="http://some/xml/namespace"
. I don't know whether you really want this or if that's just an attempt at "voodoo programming", but it will change the result significantly.
Re your question about spaces, see: https://www.w3.org/TR/1999/REC-xslt-19991116/#strip
Added: you can see it working here.