如何使用xpath替换xml中的第一个节点属性值

jas*_*ass 0 ant xpath xmltask

在下面的XML中,需要使用XPath替换命名空间.

<application xmlns="http://ns.adobe.com/air/application/4.0">
  <child id="1"></child>
  <child id="2"></child>
</application>
Run Code Online (Sandbox Code Playgroud)

我试过了

/application/@xmlns
Run Code Online (Sandbox Code Playgroud)

/*[local-name()='application']/@[local-name()='xmlns']
Run Code Online (Sandbox Code Playgroud)

两者都未能给出欲望输出.为了替换文本,我使用了xmltask替换.

<xmltask source="${temp.file1}" dest="${temp.file1}">
    <replace path="/application/@xmlns" withText="http://ns.adobe.com/air/application/16.0" />
</xmltask>
Run Code Online (Sandbox Code Playgroud)

Tom*_*lak 5

问题是这xmlns不是一个属性.您无法使用XPath选择它.

命名空间是XML节点名称的一部分:<foo xmlns="urn:foo-namespace" /><foo xmlns="urn:bar-namespace" />不是具有相同的名称和不同属性的两个节点,它们与不同的名称和两个节点没有属性.

如果要更改命名空间,则必须构造一个全新的节点.

XSLT更适合这项任务:

<!-- 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>
Run Code Online (Sandbox Code Playgroud)

这个XSLT转换做了两件事:

  • 第一个模板(标识模板)递归地复制节点,除非给定节点有更好的匹配模板
  • 第二个模板匹配air4命名空间中的元素,并构造具有相同本地名称但具有不同命名空间的新元素.这是因为XSLT中的默认名称空间声明.该http://ns.adobe.com/air/application/16.0命名空间用于所有新建的元素.

应用于您的输入XML,结果是

<application xmlns="http://ns.adobe.com/air/application/16.0">
  <child id="1"/>
  <child id="2"/>
</application>
Run Code Online (Sandbox Code Playgroud)

您可以使用Ant的xslt任务:

<xslt in="${temp.file1}" out="${temp.file1}" style="update-air-ns.xsl" />
Run Code Online (Sandbox Code Playgroud)