XML命名空间移除失败:XSLT转换结果不符合预期求助
移除XML命名空间的XSLT问题
问题说明
尝试将带命名空间的XML转换为无命名空间XML,但转换结果仍保留命名空间,且节点名称不符合预期,请求解决。
输入XML
<ns1:FieldResponse xmlns:ns1="http://www.example.org"> <ns1:response> <ns1:Elements> <ns1:workRequestId>12123</ns1:workRequestId> </ns1:Elements> </ns1:response> <ns1:Status>1232</ns1:Status> </ns1:FieldResponse>
预期输出
<?xml version="1.0" encoding="UTF-8"?> <response> <Elements> <workRequestId>12123</workRequestId> </Elements> </response> <Status>1232</Status>
当前XSLT转换输出
<?xml version="1.0" encoding="UTF-8"?> <response xmlns:ns1="http://www.example.org"> <cmElements> <workRequestId>12123</workRequestId> </cmElements> </response> <Status xmlns:ns1="http://www.example.org">1232 </Status>
所用XSLT
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:ns1="http://www.example.org" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <response> <Elements> <workRequestId> <xsl:value-of select="/ns1:FieldResponse/ns1:response/ns1:Elements/ns1:workRequestId"/> </workRequestId> </Elements> <xsl:for-each select="/ns1:FieldResponse/ns1:response/ns1:fault"> <fault> <xsl:for-each select="./*"> <xsl:element name="{local-name()}"> <xsl:value-of select="."/> </xsl:element> </xsl:for-each> </fault> </xsl:for-each> </response> <Status> <xsl:value-of select="/ns1:FieldResponse/ns1:Status"/> </Status> </xsl:template> </xsl:stylesheet>
解决方案
问题分析
- 命名空间残留:原XSLT样式表声明了
ns1命名空间,直接写<response>这类节点时,XSLT会自动继承该命名空间到输出节点中,导致残留xmlns:ns1属性。 - 节点结构硬编码:原模板通过硬编码节点路径和名称生成输出,灵活性差,且易出现节点名称不匹配的问题。
修正后的XSLT
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:ns1="http://www.example.org" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="ns1"> <!-- 声明不输出指定命名空间前缀 --> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 匹配根节点,触发子节点处理 --> <xsl:template match="/"> <xsl:apply-templates select="ns1:FieldResponse/ns1:response"/> <xsl:apply-templates select="ns1:FieldResponse/ns1:Status"/> </xsl:template> <!-- 匹配所有ns1命名空间下的元素,生成无命名空间的同名元素 --> <xsl:template match="ns1:*"> <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="text()"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
关键说明
exclude-result-prefixes="ns1":明确告知XSLT不要将ns1命名空间输出到结果中,彻底避免命名空间残留。- 模板匹配
ns1:*:递归处理所有命名空间下的元素,自动生成无命名空间的同名节点,无需硬编码节点路径,适配更复杂的XML结构。 - 通过
xsl:apply-templates驱动节点处理,保留原XML的层级结构和内容,确保输出与预期一致。
内容的提问来源于stack exchange,提问作者sri
相关产品推荐
相关产品推荐

