You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除XML中多余的命名空间前缀声明?

问题

输入XML如下:

<message xmlns="http://www.ns1.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <elem1 id="att1">
    <elem2 i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
  </elem1>
</message>

需要通过XSLT转换为指定格式,要求:

  • 将nil属性的前缀从i改为xsi
  • 仅根节点保留命名空间声明,子节点上的多余命名空间声明必须移除

期望输出:

<?xml version="1.0" encoding="utf-8"?>
<message xmlns="http://www.ns1.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <elem1 id="att1">
    <elem2 xsi:nil="true"/>
  </elem1>
</message>

尝试了以下XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.ns1.com"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
  exclude-result-prefixes="i">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="@i:nil">
    <xsl:attribute name="xsi:nil">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

但转换后elem2节点仍保留了多余的xmlns:i声明,不符合要求:

<?xml version="1.0" encoding="utf-8"?>
<message xmlns="http://www.ns1.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <elem1 id="att1">
    <elem2 xsi:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
  </elem1>
</message>

仅修改样式表能否实现需求?

解决方案

可以实现需求。原样式表仅处理了@i:nil属性的替换,但未处理子节点上的多余命名空间声明。需要新增模板来过滤非根节点的命名空间属性,同时保留根节点的必要声明。

修改后的XSLT如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.ns1.com"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
  exclude-result-prefixes="i">
  
  <xsl:output method="xml" indent="yes" encoding="utf-8"/>

  <!-- 基础复制模板:复制所有节点和属性 -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 将i:nil属性替换为xsi:nil -->
  <xsl:template match="@i:nil">
    <xsl:attribute name="xsi:nil">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

  <!-- 保留根节点的命名空间声明 -->
  <xsl:template match="*[not(parent::node())]/@*[namespace-uri()='http://www.w3.org/2000/xmlns/']" priority="1"/>
  
  <!-- 移除所有非根节点的命名空间声明 -->
  <xsl:template match="*[parent::node()]/@*[namespace-uri()='http://www.w3.org/2000/xmlns/']"/>
</xsl:stylesheet>

关键说明:

  1. 新增的两个模板专门处理命名空间属性(命名空间为http://www.w3.org/2000/xmlns/的属性):
    • 第一个模板通过*[not(parent::node())]匹配根节点,保留其命名空间声明
    • 第二个模板过滤所有非根节点上的命名空间声明,直接忽略不输出
  2. 原有的属性替换模板正常工作,完成i:nil到xsi:nil的转换
  3. exclude-result-prefixes="i"确保样式表内部声明的i前缀不会被输出到结果中

使用该样式表转换后,即可得到符合要求的输出,子节点不会保留多余的命名空间声明。

内容的提问来源于stack exchange,提问作者Owen Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 22:43:21