XSLT 在与根元素具有相同命名空间声明的内部标记中缺少命名空间

Posted

技术标签:

【中文标题】XSLT 在与根元素具有相同命名空间声明的内部标记中缺少命名空间【英文标题】:XSLT missing namespaces in inner tags that have same namespace declaration as the root element 【发布时间】:2017-11-11 15:01:44 【问题描述】:

我想创建这样的 xml:

<rns:RootElement xmlns:rns="urn:root-element" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:root-element root-element.xsd">
    <rns:DocumentWrapper>
        <ins:InnerDoc xmlns:ins="urn:inner-doc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:inner-doc inner-doc.xsd">
            <ins:Value>Some text</ins:Value>
        </ins:InnerDoc>
    </rns:DocumentWrapper>
</rns:RootElement>

使用此模板:

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

<xsl:template match="/">

    <rns:RootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xmlns:rns="urn:root-element"
                     xsi:schemaLocation="urn:root-element root-element.xsd">
        <rns:DocumentWrapper>
            <ins:InnerDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xmlns:ins="urn:inner-doc"
                          xsi:schemaLocation="urn:inner-doc inner-doc.xsd">
                <ins:Value><xsl:value-of select="//*[local-name()='SomeNode']"/></ins:Value>
            </ins:InnerDoc>
        </rns:DocumentWrapper>
    </rns:RootElement>

</xsl:template>

但不是我想要的结果,这个模板给了我一点不同的结果:

<rns:RootElement xmlns:rns="urn:root-element" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:root-element root-element.xsd">
    <rns:DocumentWrapper>
        <ins:InnerDoc xmlns:ins="urn:inner-doc" xsi:schemaLocation="urn:inner-doc inner-doc.xsd">
            <ins:Value>Some text</ins:Value>
        </ins:InnerDoc>
    </rns:DocumentWrapper>
</rns:RootElement>

如您所见,在转换结果中,InnerDoc 元素缺少 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 命名空间的定义,有什么办法可以防止丢失这个命名空间?

【问题讨论】:

为了稍微扩展 Martin Honnen 的回答,我想指出缺少重复的 ins 命名空间声明没有任何作用。任何符合标准的 XML 处理器都将认识到根元素上的 ins 命名空间声明也适用于此 ins:InnerDoc 元素。任何将这个ins:InnerDoc 元素的位置移动到其他位置(根元素上的声明不适用)的一致 XSL 处理器也将根据需要添加到命名空间声明中。 我知道,但是这个要求来自其他系统,我真的不知道如果没有这个命名空间他们会正确接收我的消息。无论如何,谢谢你的评论! 【参考方案1】:

由于命名空间声明 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 存在于根元素上,它在子元素和后代元素的范围内,不需要为 ins:InnerDoc 元素重复。我不知道用 XSLT 强制输出重复的命名空间声明的任何方法。

其他一些 API 有一种方法来抑制它们,例如 LINQ to XML 与 SaveOptions https://msdn.microsoft.com/en-us/library/system.xml.linq.saveoptions(v=vs.110).aspx 上的 OmitDuplicateNamespaces,但添加该选项是为了在序列化 LINQ to XML 树时抑制重复的命名空间声明,而不是强制执行。

【讨论】:

感谢您的回答!我在想类似的事情,看来我需要以其他方式处理我的问题。

以上是关于XSLT 在与根元素具有相同命名空间声明的内部标记中缺少命名空间的主要内容,如果未能解决你的问题,请参考以下文章

使用 xslt 引用具有不同命名空间的元素

xslt copy-of到结果文档中的不同命名空间

重命名元素的 XSLT 问题——更改命名空间

XML 元素名称中包含的 XSLT 命名空间 URI

使用命名空间时无法在 XSLT 中复制和修改属性

选择字段元素时不确定 XSLT 文档中的当前路径