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

如何用XSLT移除XML指定xmlns声明且保留带命名空间的元素

我来帮你搞定这个XSLT的问题!你的需求很明确:移除XML里所有的xmlns声明,但要保留带shipping前缀的元素和message:timestamp属性。不过当前的XSLT代码会把shipping:min、shipping:max的前缀给去掉,完全不符合预期,咱们来调整一下:

问题回顾

原始XML

<Orders xmlns="hi/hi" xmlns:shipping="hello/hi" xmlns:message="hello/hi" message:timestamp="2018-04-23T14:28:39Z"> 
  <orderLineStatusUpdate orderNumber="CCORD002" line="0"> 
    <orderLineStatus>inPicking</orderLineStatus> 
    <shipmentNumber>1</shipmentNumber> 
    <leadTime unit="days"> 
      <shipping:min>1</shipping:min> 
      <shipping:max>1</shipping:max> 
    </leadTime> 
  </orderLineStatusUpdate> 
</Orders>

期望输出

<Orders message:timestamp="2018-04-23T14:28:39Z"> 
  <orderLineStatusUpdate orderNumber="CCORD002" line="0"> 
    <orderLineStatus>inPicking</orderLineStatus> 
    <shipmentNumber>1</shipmentNumber> 
    <leadTime unit="days"> 
      <shipping:min>1</shipping:min> 
      <shipping:max>1</shipping:max> 
    </leadTime> 
  </orderLineStatusUpdate> 
</Orders>

当前错误的XSLT代码

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
  <xsl:output method="xml" indent="yes" /> 
  <xsl:template match="*"> 
    <xsl:element name="{local-name(.)}"> 
      <xsl:apply-templates select="@* | node()" /> 
    </xsl:element> 
  </xsl:template> 
  <xsl:template match="@*"> 
    <xsl:attribute name="{local-name(.)}"> 
      <xsl:value-of select="." /> 
    </xsl:attribute> 
  </xsl:template> 
  <xsl:template match="@*[local-name(.)='message']" /> 
</xsl:stylesheet>
问题分析

当前代码的问题出在这几点:

  • 处理元素时用了local-name(.),会直接去掉所有元素的前缀,导致shipping:min变成min,完全丢失了前缀标识;
  • 处理属性时同样用了local-name(.),会把message:timestamp的前缀去掉,变成普通的timestamp属性;
  • 最后一个模板匹配@*[local-name(.)='message']完全是错误的,它试图删除名为message的属性,但我们要删除的是xmlns相关的声明,不是message前缀的属性。
正确的XSLT实现

我们需要调整模板逻辑,确保保留元素的前缀,同时只移除xmlns和xmlns:*属性,其他属性(包括带前缀的message:timestamp)全部保留:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>

  <!-- 身份模板:复制文本、注释、处理指令等非元素/属性节点 -->
  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 复制元素:保留原名称(包括前缀) -->
  <xsl:template match="*">
    <xsl:element name="{name()}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <!-- 处理属性:排除xmlns和xmlns:*属性,其他保留原名称 -->
  <xsl:template match="@*">
    <xsl:if test="not(starts-with(name(), 'xmlns'))">
      <xsl:attribute name="{name()}">
        <xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
代码说明
  • 身份模板:专门处理文本节点、注释、处理指令等非元素/属性节点,直接复制它们,避免内容丢失;
  • 元素模板:用name()代替local-name(.),这样会完整保留元素的前缀(比如shipping:min会原样保留);
  • 属性模板:通过starts-with(name(), 'xmlns')判断是否是命名空间声明属性,是的话跳过移除,其他属性(包括message:timestamp)都保留原名称和值。

用这个代码处理后,就能得到你想要的结果:所有xmlns声明被移除,shipping前缀的元素和message:timestamp属性都完整保留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:58:39