Xml XSLT删除空白名称空间,而不将元素分配给不同的名称空间或默认名称空间
我有以下XML:Xml XSLT删除空白名称空间,而不将元素分配给不同的名称空间或默认名称空间,xml,xslt,namespaces,Xml,Xslt,Namespaces,我有以下XML: <ns1:A xmlns:ns1="http://www.namespace1.com" xmlns:ns2="http://www.namespace2.com"> <B> <C>123</C> </B> <ns2:D> <E>456</E> </ns2:D> </ns1:A> 123 456 我想使用以下XSLT对其进行转换: <
<ns1:A xmlns:ns1="http://www.namespace1.com" xmlns:ns2="http://www.namespace2.com">
<B>
<C>123</C>
</B>
<ns2:D>
<E>456</E>
</ns2:D>
</ns1:A>
123
456
我想使用以下XSLT对其进行转换:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="xsl xs xsi">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="@*|namespace::*[name()]"/>
<xsl:if test="text() != ''">
<xsl:value-of select="concat(text(), 'xyz')"/>
</xsl:if>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
对于元素B和E,输出具有不需要的空白名称空间:
<A xmlns="http://www.namespace1.com" xmlns:ns1="http://www.namespace1.com" xmlns:ns2="http://www.namespace2.com">
<B xmlns="">
<C>123xyz</C>
</B>
<D xmlns="http://www.namespace2.com">
<E xmlns="">456xyz</E>
</D>
</A>
123xyz
456xyz
我的愿望是删除输出中的空白命名空间。我看过很多关于指定默认名称空间或将元素指定给某个父名称空间的帖子。然而,这不是我想要的。在输出中,我确实希望元素B、C和E保留在“空白”名称空间中,因为这是相应的XSD所需要的(由于遗留原因,我无法更新XSD)。因此,期望的输出是:
<A xmlns="http://www.namespace1.com" xmlns:ns1="http://www.namespace1.com" xmlns:ns2="http://www.namespace2.com">
<B>
<C>123xyz</C>
</B>
<D xmlns="http://www.namespace2.com">
<E>456xyz</E>
</D>
</A>
123xyz
456xyz
如何去除输出中的空白命名空间?我还想指出,XSLT将应用于具有不同模式结构的不同输入XML,因此XSLT必须尽可能通用,而不必硬编码元素或名称空间名称
编辑:
回顾M.Kay和M.Hor的回答,我意识到我之前的“期望”输出是不正确的。正如M.Hor所解释的,默认名称空间是继承的,正如我之前的“所需”输出中所列出的,这也不是我想要的。(对于不正确的“所需”输出表示抱歉)
我(更正)所需的输出是不使用任何默认名称空间,而是使用名称空间前缀:
<ns1:A xmlns:ns1="http://www.namespace1.com" xmlns:ns2="http://www.namespace2.com">
<B>
<C>123xyz</C>
</B>
<ns2:D>
<E>456xyz</E>
</ns2:D>
</ns1:A>
123xyz
456xyz
我已经更新了XSLT作为下面这个问题的答案,它输出了我想要的内容
谢谢!
IK
(输入和输出相同,只是因为我使用的是简化的
XSLT)
当XSLT实际上没有改变任何东西时,很难理解这个问题。对于声明的目的,模板应该可以正常工作:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="2.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:stylesheet>
编辑 响应您的编辑,显示不同的所需输出: 你说: 我确实希望元素B、C和E保留在“空白”名称空间中 但这是而不是所需输出中发生的情况:
<A xmlns="http://www.namespace1.com" xmlns:ns1="http://www.namespace1.com"
xmlns:ns2="http://www.namespace2.com">
<B>
<C>123xyz</C>
</B>
<D xmlns="http://www.namespace2.com">
<E>456xyz</E>
</D>
</A>
123xyz
456xyz
在这里,元素B
和C
从它们的A
祖先继承它们的名称空间。类似地,E
元素与其D
父元素位于同一命名空间中
当您声明默认名称空间时,它就是这样工作的:声明范围内的所有元素都放置在该名称空间中。为了将
B
放置在无命名空间中,必须进行显式异常。这就是您在实际结果中看到
的原因。当您说xmlns=”“
声明不受欢迎时,您的意思大概是希望B元素位于名称空间http://www.namespace1.com
。因此,您需要做的是将它放在该名称空间中。您使用指令
创建了元素,因此您显式地将新的B元素与旧的B元素放在同一名称空间中(即,不放在名称空间中)。如果要将其放在不同的名称空间中,只需更改此指令。以下XSLT将输出名称空间前缀,而不输出默认名称空间,从而避免输出中的xmlns=”“
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="xsl xs xsi">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="@*|namespace::*[name()]"/>
<xsl:if test="text() != ''">
<xsl:value-of select="concat(text(), 'xyz')"/>
</xsl:if>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
基本上,我没有使用local-name(),而是使用name()来包含前缀
现在输出为:
<ns1:A xmlns:ns1="http://www.namespace1.com" xmlns:ns2="http://www.namespace2.com">
<B>
<C>123xyz</C>
</B>
<ns2:D>
<E>456xyz</E>
</ns2:D>
</ns1:A>
123xyz
456xyz
注意:这是使用Saxon Home Edition 9.4测试的。我注意到其他XSLT处理器可能仍然会输出xmlns=“”。你是对的,我最初的问题有点不清楚-我已经更新了我的问题以使其更清楚。标识转换不是我想要的,因为输出将与输入XML不同。我的主要问题是去掉输出XMLNS=“的空白命名空间”,同时保持元素B、C和E没有指定的命名空间。@ ILK可以简单地将<代码> xSL:I/<代码>及其内容添加到身份转换模板中。或者(在现实场景中更可能)在必要时添加更多特定模板以覆盖标识转换。但是您提到的“主要问题”无法按照您提出的方式解决-请参阅我的答案的编辑以了解原因。谢谢您-您的解释使我意识到我想要的输出(带有默认名称空间)也不是我想要的。我已经用修改后的期望输出编辑了我的问题。谢谢你的回答-我意识到我以前期望的输出是不正确的。我已经更新了我的问题,列出了更正后的所需输出。可能最好打开一个新问题。修改答案来回答修改过的问题会让人太困惑。你的第一个模板是多余的:内置的模板规则可以帮你做到这一点。您的第二个模板基本上与身份转换模板做相同的事情。瞧,你又回到了我在第一版回答中提到的情况。