Reputation: 13690
I want to add a node to an XML document using xslt. I am using msxsl as processor. The XML document has this structure:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PlatformShortName>SDK_NAME</PlatformShortName>
</PropertyGroup>
</Project>
The XSL rule inserts the desired node:
(Edit: added the XSL namespace)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="http://schemas.microsoft.com/developer/msbuild/2003"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
exclude-result-prefixes="ms">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="ms:Project/ms:PropertyGroup">
<PropertyGroup>
<xsl:element name="PlatformInstructionSet">AMRv7</xsl:element>
<xsl:apply-templates/>
</PropertyGroup>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
But the result has moved the namespace attribute from Project
to PropertyGroup
.
(Edit: I want the Project
and the PropertyGroup
identical to the input.)
<Project>
<PropertyGroup xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PlatformInstructionSet>AMRv7</PlatformInstructionSet>
<PlatformShortName>SDK_NAME</PlatformShortName>
</PropertyGroup>
</Project>
It's necessary to avoid it. How can I only add an node without changing the structure? Additionall I would like to have the new node inserted like the other nodes.
Upvotes: 0
Views: 67
Reputation: 1695
For the input you have provided, the templates can be rewritten as following:
<xsl:template match="ms:Project/ms:PropertyGroup">
<PropertyGroup xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<xsl:element name="PlatformInstructionSet">AMRv7</xsl:element>
<xsl:apply-templates />
</PropertyGroup>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="http://schemas.microsoft.com/developer/msbuild/2003">
<xsl:apply-templates select="node() | @*"/>
</xsl:element>
</xsl:template>
Note:
Adding xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
in <PropertyGroup>
would consider it's child to be in the same namespace as the parent and hence it won't add it in child node.
Also it will add xmlns=""
in <PropertyGroup>
if the namespace is not added to this node. (specifically for this case with given template)
Upvotes: 0
Reputation: 116993
It's not clear what your expected output is.
If you want to keep the original namespace and insert the new element into it, then do:
XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="http://schemas.microsoft.com/developer/msbuild/2003"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
exclude-result-prefixes="ms">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ms:PropertyGroup">
<xsl:copy>
<PlatformInstructionSet>AMRv7</PlatformInstructionSet>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If you want to remove the namespace altogether, then do:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="http://schemas.microsoft.com/developer/msbuild/2003"
exclude-result-prefixes="ms">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="ms:PropertyGroup">
<PropertyGroup>
<PlatformInstructionSet>AMRv7</PlatformInstructionSet>
<xsl:apply-templates/>
</PropertyGroup>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0