【问题标题】:XSL for removing or changing empty xmlns on xml documentXSL 用于删除或更改 xml 文档上的空 xmlns
【发布时间】:2021-04-29 16:58:00
【问题描述】:

一个同步 SOAP Web 服务正在使用一个 xml 文档响应我的请求,该文档具有一个带有空 xmlns 属性 (<element xmlns="">value</element>) 的元素。当然,这会扰乱负责处理此响应的程序。

我想应用 XSL 转换来摆脱空 xmlns 或将其更改为正确的命名空间。 到目前为止,我在此处或其他网站中找到的 XSL 样式表不起作用或使固定元素的子元素现在具有空的 xmlns。 我的输入xml文档如下:

<?xml version="1.0" encoding="utf-8"?>
    <rootElement xmlns="http://tempuri.org/">
        <level1>
            <level2 xmlns="">
                <child1 id="aNumber" desc="aString">
                    <name>name1</name>
                    <code>code1</code>
                </child1>
                <child2 desc="aString">
                    <field1>field1</field1>
                    <field2>field2</field2>
                </child2>
            </level2>
        </level1>
    </rootElement>

到目前为止,我在这里找到的一些 xsl 样式表的最佳输出是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<rootElement xmlns="http://tempuri.org/">
        <level1>
            <level2>
                  <child1 xmlns="" desc="aString" id="aNumber">
                        <name>name1</name>
                        <code>code1</code>
                  </child1>
                  <child2 xmlns="" desc="aString">
                        <field1>field1</field1>
                        <field2>field2</field2>
                  </child2>
            </level2>
        </level1>
    </rootElement>

level2 是固定的,但现在 child1 和 child 2 都有一个空的 xmlns。这也使我的程序失败。 到目前为止,我得到的最好和最简单的样式表是这个:

<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns="http://tempuri.org/">
    <xsl:output encoding='UTF-8' indent='yes' method='xml'/>
    <!-- copy everything into the output -->
    <xsl:template match='@*|node()'>
        <xsl:copy>
            <xsl:apply-templates select='@*|node()'/>
        </xsl:copy>
    </xsl:template>
    <!-- change the namespace declaration for level2 -->
    <xsl:template match="level2">
        <level2 xmlns='http://tempuri.org/'>
            <xsl:copy-of select="@*|node()"/>
        </level2>
    </xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 你为什么说它“当然”在搞乱程序? xmlns="" 在 XML 中是完全正常的。您如何处理响应?也许您只需要调整处理方式即可。
  • 嗨。空 xmlns 使 level2 元素及其所有子元素属于另一个命名空间,而不是来自根元素的命名空间。我的程序基于此工作,如果它不属于与根元素相同的命名空间,它就找不到元素 level2。不幸的是,改变程序是不可能的。
  • @juankinspain 空的 xmls 不是 “使 level2 元素及其所有子元素都属于另一个命名空间”。它所做的只是反映这些元素实际上位于另一个名称空间中的事实。它们是由 XML 作者放在那里的。

标签: xml xslt xml-namespaces


【解决方案1】:

摆脱空的 xmlns 或将其更改为正确的命名空间。

除了将无命名空间中的元素移动到与其父/祖先元素相同的命名空间之外,没有其他方法可以“摆脱空的 xmlns”:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="*[not(namespace-uri(.))]">
    <xsl:element name="{local-name()}" namespace="http://tempuri.org/">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

或者,您可以将所有元素移动到无命名空间:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

但是,这两种解决方案都有缺陷;必须假设命名空间的存在是有充分理由的。去掉&lt;elem xmlns="http://tempuri.org/"&gt;&lt;elem&gt; 之间的区别可能会产生意想不到的结果。

【讨论】:

  • 第一个替代方案就像一个魅力。非常感谢。
猜你喜欢
  • 2018-03-12
  • 1970-01-01
  • 2013-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-01
  • 1970-01-01
相关资源
最近更新 更多