我使用的是Microsoft的XSLT处理器(仅限1.0)
XML开头行:
<?xml version="1.0" encoding="utf-8"?>
<Header xmlns="http:\\OldNameSpace.com">
<Detail>
使用以下XSLT模板来获取文档的<Header>
元素并更改其命名空间。
<xsl:template match="*">
<xsl:element name="{name()}" xmlns="http:\\NewNameSpace.com">
<xsl:copy-of select="@*"/>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
将<Header xmlns="http:\\OldNameSpace.com">
变为<Header xmlns="http:\\NewNameSpace.com">
但是我现在需要为此添加第二个命名空间,以便获得以下输出:
<Header xmlns="NewNameSpace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
我尝试过使用:
<xsl:template match="*">
<xsl:element name="{name()}" xmlns="NewNameSpace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:copy-of select="@*"/>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
但是我仍然只获得与原始XSLT模板相同的输出。
有人可以告诉我为什么会这样吗?
答案 0 :(得分:5)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="http:\\OldNameSpace.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="old xsi">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pNewNamespace" select="'http:\\NewNameSpace.com'"/>
<xsl:variable name="vXsi" select="document('')/*/namespace::*[name()='xsi']"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="old:*">
<xsl:element name="{local-name()}" namespace="{$pNewNamespace}">
<xsl:copy-of select="$vXsi"/>
<xsl:copy-of select="@*"/>
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
应用于以下XML文档:
<Header xmlns="http:\\OldNameSpace.com">
<Detail/>
</Header>
产生(我猜的是)想要的正确结果:
<Header xmlns="http:\\NewNameSpace.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Detail/>
</Header>
答案 1 :(得分:2)
xsl:element(与文字结果元素不同)不将范围名称空间中的所有内容复制到结果中,只是元素名称所需的名称空间9可以隐式地从其名称或命名空间参数指定)。
xslt2为这种情况添加了一个xsl:namespace指令,但在xslt1中最简单的事情就是
,其中
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
在祖先的某个地方(例如在xsl:stylesheet上。)
将向输出添加虚假xsi:tmp=""
,然后添加名称空间声明,
如果你真的需要这个命名空间中的一个属性,例如xsi:type
在上面使用它而不是tmp,你就完成了。如果你不介意xsi命名空间中的额外的,可能是无效的属性,你就完成了。否则在变量中执行上述操作,然后使用msxsl:node-set
查询变量并删除虚假的额外属性。
答案 2 :(得分:2)
如果您静态地知道要生成的命名空间,那么在XSLT 1.0中执行此操作的最简单方法是使用xsl:copy-of。创建源文档<dummy xmlns:xsi="http://whatever"/>
,
然后在<xsl:copy-of select="document('dummy.xml')/*/namespace::xsi"/>
的电话中xsl:element
进行操作。