【发布时间】:2017-11-27 02:57:12
【问题描述】:
我正在编写一个 XSLT 转换,我希望在根元素上定义所有命名空间前缀。默认情况下,MS 似乎会在 XML 层次结构中的第一个元素上创建一个新的前缀定义以使用该模式;这意味着如果多个元素与同一架构的共享祖先不相关,则可以在多个元素上引用相同的架构。
通过对根元素进行这样的编码,一切都可以正常工作:
<!-- ... -->
<ns0:root xmlns:ns0="http://some/schema" xmlns:ns1 = "http://another/schema">
<!-- rest of XSLT; including calls to other templates -->
</ns0:root>
<!-- ... -->
但是我找不到任何使用xsl:element 编码的方法;例如
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://some/schema"
xmlns:ns1 = "http://another/schema"
>
<!-- ... -->
<xsl:element name="ns0:root">
<xsl:attribute name="ns1" namespace="http://www.w3.org/2000/xslns/">http://another/schema</xsl:attribute>
<!-- rest of XSLT; including calls to other templates -->
</xsl:element>
<!-- ... -->
是否可以针对 xls:element 为该元素本身以外的模式声明命名空间前缀?
完整示例
XML
<Demo xmlns="http://some/schema">
<a>Hello</a>
<b>World</b>
</Demo>
XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://some/schema"
xmlns:ns1 = "http://another/schema"
exclude-result-prefixes="xsl"
>
<xsl:output method="xml" indent="yes" version="1.0"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="/ns0:Demo/ns0:a">
<xsl:element name="ns1:z">
<xsl:value-of select="./text()" />
</xsl:element>
</xsl:template>
<xsl:template match="/ns0:Demo/ns0:b">
<xsl:element name="ns1:y">
<xsl:value-of select="./text()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
结果
<Demo xmlns="http://some/schema">
<ns1:z xmlns:ns1="http://another/schema">Hello</ns1:z>
<ns1:y xmlns:ns1="http://another/schema">World</ns1:y>
</Demo>
期望的结果
<Demo xmlns="http://some/schema" xmlns:ns1="http://another/schema">
<ns1:z>Hello</ns1:z>
<ns1:y>World</ns1:y>
</Demo>
或
<ns0:Demo xmlns:ns0="http://some/schema" xmlns:ns1="http://another/schema">
<ns1:z>Hello</ns1:z>
<ns1:y>World</ns1:y>
</ns0:Demo>
【问题讨论】:
-
您可能希望向我们展示最小但完整的 XML 输入示例、您拥有的 XSLT 代码、您想要的结果以及您获得的结果,以便我们重现和理解问题。
<xsl:element name="ns0:root">的 sn-p 似乎没有必要,因为你没有在运行时计算元素名称,所以我不确定你为什么需要xsl:element。如果您希望命名空间声明在所有模板中的所有结果元素的范围内,那么您可以将它们放在xsl:stylesheet上,但似乎您已经拥有了。 -
不用担心;请参阅更新版本的“完整示例”部分。
-
你为什么在乎?您呈现的期望结果和实际结果具有相同的语义。
-
@JohnBollinger 可读性和文件大小。当有数百个同级元素时,使用模式定义所有元素会使它们更难阅读,并显着增加文件大小。还有好奇心。同意我可以让这个 XSL 工作;但我觉得应该可以让它按照我想要的方式工作(特别是考虑到使用
<Root>代替<xsl:element name="Root">/<xsl:element name="{name(.)}">; 当你期望所有方法都有相同的行为时(除了最后一个的名称根据输入 XML 的根元素而变化)。
标签: c# .net xslt xslcompiledtransform