0

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.

harper
  • 13,345
  • 8
  • 56
  • 105
  • You're not showing an important part of your stylesheet: the namespace declarations in the header. And it's not clear what the output should be. – michael.hor257k Feb 15 '19 at 09:02
  • The result you show is not the result received: https://xsltfiddle.liberty-development.net/94rmq5V – michael.hor257k Feb 15 '19 at 09:32
  • That's because he added this `xmlns="http://schemas.microsoft.com/developer/msbuild/2003" exclude-result-prefixes="ms"`. If it will be removed, the problem can be reproduced. – Vebbie Feb 15 '19 at 09:38

2 Answers2

0

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)

Vebbie
  • 1,669
  • 2
  • 12
  • 18
0

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>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51