0

In the below XML, need to replace the namespace by using XPath.

<application xmlns="http://ns.adobe.com/air/application/4.0">
  <child id="1"></child>
  <child id="2"></child>
</application>

I tried with

/application/@xmlns

and

/*[local-name()='application']/@[local-name()='xmlns']

Both failed to give the desire output. To replace the text, I have used xmltask replace.

<xmltask source="${temp.file1}" dest="${temp.file1}">
    <replace path="/application/@xmlns" withText="http://ns.adobe.com/air/application/16.0" />
</xmltask>
Tomalak
  • 332,285
  • 67
  • 532
  • 628
jass
  • 343
  • 2
  • 6
  • 16

1 Answers1

5

The problem is that xmlns is not an attribute. You cannot select it with XPath.

A namespace is part of the node name in XML: <foo xmlns="urn:foo-namespace" /> and <foo xmlns="urn:bar-namespace" /> are not two nodes with the same name and different attributes, they are two nodes with different names and no attributes.

If you want to change a namespace, you must construct a completely new node.

XSLT is better-suited to this task:

<!-- update-air-ns.xsl -->
<xsl:transform
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:air4="http://ns.adobe.com/air/application/4.0"
    xmlns="http://ns.adobe.com/air/application/16.0"
>
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="air4:*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
</xsl:transform>

This XSLT transformation does two things:

  • the first template (identity template) copies nodes recursively, unless there is a better matching template for a given node
  • the second template matches elements in the air4 namespace and constructs new elements that have the same local name but a different namespace. This happens because of the default namespace declaration in the XSLT. The http://ns.adobe.com/air/application/16.0 namespace is used for all newly constructed elements.

Applied to your input XML, the result is

<application xmlns="http://ns.adobe.com/air/application/16.0">
  <child id="1"/>
  <child id="2"/>
</application>

You can use Ant's xslt task:

<xslt in="${temp.file1}" out="${temp.file1}" style="update-air-ns.xsl" />
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Can you plz explain the xsl task. i have tried the above snippets since its failed to replace. – jass Feb 06 '15 at 12:14
  • I think it you will need to take a tour to the documentation if you want to know how the `xslt` task works. I have explained why the `xmltask` cannot do what you want and provided a solution that does what you want. *Integrating* the solution is your job. – Tomalak Feb 06 '15 at 12:20