XSL:删除命名空间前缀

Posted

技术标签:

【中文标题】XSL:删除命名空间前缀【英文标题】:XSL: Remove namespace prefix 【发布时间】:2014-10-24 09:25:55 【问题描述】:

搜索了一段时间后,我想我会在这里问。我正在尝试从 XSL 输出文件中删除空名称空间。让我提供相关代码:

输入 XML

<?xml version="1.0" encoding="UTF-8"?>
<DK_RequestChangeOfSupplier xmlns="un:unece:260:data:EEM-DK_RequestChangeOfSupplier:v2">
    <HeaderEnergyDocument>
        <Creation>Date</Creation>
    </HeaderEnergyDocument>
</DK_RequestChangeOfSupplier>

XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:ns1="un:unece:260:data:EEM-DK_RequestChangeOfSupplier:v2"
            exclude-result-prefixes="ns1">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
            indent="yes" omit-xml-declaration="no"/>

    <xsl:template match="/">
        <xsl:for-each select="ns1:DK_RequestChangeOfSupplier">
            <McsDkSMBMsg 
             xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg">
                <xsl:call-template name="CreateElement">
                    <xsl:with-param name="ElementName" select="'Creation'" />
                </xsl:call-template>
            </McsDkSMBMsg>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="CreateElement">
        <xsl:param name="ElementName"></xsl:param>
        <xsl:element name="$ElementName">Testing</xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出

<McsDkSMBMsg xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg">
    <Creation xmlns="">Testing</Creation>
</McsDkSMBMsg>

如何删除命名空间?我在 XSL 方面做错了什么吗?我慢慢地把头发拉出来。问候。

【问题讨论】:

您使用的是什么 XSLT 处理器?我无法重现您对 Saxon 或 Xalan 的问题。 XSL 不正确,已被编辑。您现在应该可以重现它了。 最简单的解决方法是将xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg" 声明移动到***xsl:stylesheet 元素上。 “感谢上帝,这个 XML 中有命名空间”,没有人说过... 【参考方案1】:

您的原始代码将两个元素添加到输出树中:一个名为 McsDkSMBMsg 的元素具有 默认命名空间

<McsDkSMBMsg xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg">

另一个是Creation - 根据您的原始代码,它根本就在没有命名空间中。 XSLT 处理器确保Creation 元素不会出现在默认命名空间中的唯一方法是取消声明此命名空间:

<Creation xmlns="">Testing</Creation>

我假设您希望 Creation 元素也属于该默认命名空间。如果是这样,只需将相同的xmlns 属性添加到创建Creationxsl:element 指令。 XLST 处理器将处理任何多余的命名空间声明。

样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:ns1="un:unece:260:data:EEM-DK_RequestChangeOfSupplier:v2"
            exclude-result-prefixes="ns1">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
            indent="yes" omit-xml-declaration="no"/>

    <xsl:template match="/">
        <xsl:for-each select="ns1:DK_RequestChangeOfSupplier">
            <McsDkSMBMsg 
             xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg">
                <xsl:call-template name="CreateElement">
                    <xsl:with-param name="ElementName" select="'Creation'" />
                </xsl:call-template>
            </McsDkSMBMsg>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="CreateElement">
        <xsl:param name="ElementName"></xsl:param>
        <xsl:element name="$ElementName" xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg">Testing</xsl:element>
    </xsl:template>
</xsl:stylesheet>

XML 输出

现在xmlns 属性仅存在于McsDkSMBMsg 元素上。

<?xml version="1.0" encoding="UTF-8"?>
<McsDkSMBMsg xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg">
   <Creation>Testing</Creation>
</McsDkSMBMsg>

也就是说,您的代码可能需要一些改进。您正在将 for-each 应用于最外层元素 - 其中只能有一个 - 这没有任何意义。此外,为新命名空间定义 prefix 可能更合理。而且您无缘无故地调用命名模板。

它的用处取决于实际的 XML 输入和您已有的其他代码。

改进的样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:ns1="un:unece:260:data:EEM-DK_RequestChangeOfSupplier:v2"
            xmlns:msg="http://schemas.microsoft.com/dynamics/2008/01/documents/McsDkSMBMsg"
            exclude-result-prefixes="ns1">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
            indent="yes" omit-xml-declaration="no"/>

    <xsl:template match="ns1:DK_RequestChangeOfSupplier">
            <msg:McsDkSMBMsg>
                <xsl:element name="msg:Creation">Testing</xsl:element>
            </msg:McsDkSMBMsg>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

哈哈。那太棒了。我想我必须回到 XSL 和命名空间的基础知识。谢谢! @user2980567 不客气。还请看看我建议的改进 - 也许它们有用? 它们确实很有用。我的原始 XSL 文档和输入 XML 包含的数据比描述的要多,而且我还必须保持一些严格的标准。我一定会调查的。谢谢。

以上是关于XSL:删除命名空间前缀的主要内容,如果未能解决你的问题,请参考以下文章

如何将命名空间前缀设置为有效负载 xsl

如何从输出 xml 中删除命名空间?

删除带有命名空间前缀的 xmlns 属性

使用 XLS 删除一些命名空间前缀

XSLT - 删除前缀命名空间特定节点 XML

在 JAXB 编组时删除命名空间前缀