Reputation: 41
i have xml i want to copy as is like (check xmlns="" and tags. i want to create as is .
The total calculation is taken care. only this issue . it is valid . still client want the expected format to be like that. any help greatly appreciated. three tasks
1)I need to add namespace Employees xmnls="1.2" xmlns:xsi="3" xsi:schemalocation="4"> 2)generating tag like this in the output xml not 3)need to avoid xmlns=""
any help in advance greatly appreciated rameshkumar singh
Input.xml
<Employees>
<employee>
<dept>1</dept>
<sec></sec>
</employee>
<employee>
<dept>2</dept>
<sec></sec>
</employee>
</Employees>
Expected.XML
<Employees xmnls="1.2" xmlns:xsi="3" xsi:schemalocation="4">
<totalemp>2</totalemp>
<employee>
<dept>1</dept>
<sec></sec>
<employee>
<employee>
<dept>2</dept>
<sec></sec>
<employee>
</Employees>
actual.XML
<Employees>
<totalemp>2</totalemp>
<employee xmlns="">
<dept>1</dept>
<sec/>
</employee>
<employee>
<dept>2</dept>
<sec/>
<employee>
</Employees>
Upvotes: 2
Views: 222
Reputation: 243549
This short and simple transformation (has minimum number of templates and doesn't use any explicit XSLT conditional instructions, no xsl:attribute
or priority
attributes):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="3" xsi:schemalocation="4">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()[not(self::*)]|@*">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="1.2">
<xsl:copy-of select=
"document('')/*[not(current()/../..)]
/@xsi:schemalocation"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<Employees>
<employee>
<dept>1</dept>
<sec></sec>
</employee>
<employee>
<dept>2</dept>
<sec></sec>
</employee>
</Employees>
produces the wanted, correct result:
<Employees xmlns="1.2" xmlns:xsi="3" xsi:schemalocation="4">
<employee>
<dept>1</dept>
<sec/>
</employee>
<employee>
<dept>2</dept>
<sec/>
</employee>
</Employees>
Upvotes: 0
Reputation: 6105
Here's how you do it:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="3">
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" priority="2">
<xsl:element name="{local-name()}" namespace="1.2">
<xsl:if test="self::Employees">
<xsl:attribute name="xsi:schemalocation">4</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
You apply the identity transformation as a default and then override it for elements to give them a new namespace as well as a special attribute for the Employees
node. I chose to add an if
statement but you also can move that logic into another template that matches Employees
. I just didn't want to repeat the whole xsl:element
thing twice. Matter of taste really.
When I apply this transformation to your input document I end up with:
<Employees xmlns="1.2" xmlns:xsi="3" xsi:schemalocation="4">
<employee>
<dept>1</dept>
<sec/>
</employee>
<employee>
<dept>2</dept>
<sec/>
</employee>
</Employees>
You had the xmlns=""
in your result likely because you weren't recreating all elements in that new namespace. Also, to be able to add the xsi:schemalocation
attribute you need to declare the xsi
namespace on the transformation document.
Upvotes: 3