我有一个正在发展的自定义XML模式:添加元素,删除其他元素,并更改名称空间以反映新版本(例如,从“http://foo/1.0”到“ HTTP://foo/1.1" )。我想编写一个将XML文档从旧模式转换为新模式的XSLT。我的第一次尝试是有效的,但它是冗长而不可缩放的,我需要帮助完善它。XSLT标识转换产生错误的名称空间
下面是1.0模式的样本文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo:rootElement xmlns:foo="http://foo/1.0">
<obsolete>something</obsolete>
<stuff>
<alpha>a</alpha>
<beta>b</beta>
</stuff>
</foo:rootElement>
在1.1模式中,“过时”的元素消失了,但一切依旧。所以XSLT需要做两件事情:
- 除去该标记
- 变化从http://foo/1.0的命名空间http://foo/1.1
这里是我的解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo1="http://foo/1.0"
xmlns:foo="http://foo/1.1"
exclude-result-prefixes="foo1">
<xsl:output method="xml" standalone="yes" indent="yes"/>
<!-- Remove the "obsolete" tag -->
<xsl:template match="foo1:rootElement/obsolete"/>
<!-- Copy the "alpha" tag -->
<xsl:template match="foo1:rootElement/stuff/alpha">
<alpha>
<xsl:apply-templates/>
</alpha>
</xsl:template>
<!-- Copy the "beta" tag -->
<xsl:template match="foo1:rootElement/stuff/beta">
<beta>
<xsl:apply-templates/>
</beta>
</xsl:template>
<!-- Copy the "stuff" tag -->
<xsl:template match="foo1:rootElement/stuff">
<stuff>
<xsl:apply-templates/>
</stuff>
</xsl:template>
<!-- Copy the "rootElement" tag -->
<xsl:template match="foo1:rootElement">
<foo:rootElement>
<xsl:apply-templates/>
</foo:rootElement>
</xsl:template>
</xsl:stylesheet>
虽然这将产生输出我想,请注意,我为模式中的每个元素都有一个复制模板:alpha,beta等。对于包含数百种元素的复杂模式,我会必须添加数百个模板!
我以为我可以通过降低所有这些复制模板到一个单一的身份转换,这样消除此问题:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo1="http://foo/1.0"
xmlns:foo="http://foo/1.1"
exclude-result-prefixes="foo1">
<xsl:output method="xml" standalone="yes" indent="yes"/>
<xsl:template match="foo1:rootElement/obsolete"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo1:rootElement/stuff">
<xsl:copy>
<xsl:call-template name="identity"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo1:rootElement">
<foo:rootElement>
<xsl:apply-templates/>
</foo:rootElement>
</xsl:template>
</xsl:stylesheet>
但它产生:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo:rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:foo="http://foo/1.1">
<stuff xmlns:foo="http://foo/1.0">
<stuff>
<alpha>a</alpha>
<beta>b</beta>
</stuff>
</stuff>
</foo:rootElement>
的“东西”的因素是这是我想要的,但它被另一个“东西”元素包裹,用旧的名称空间标记。我不明白为什么会发生这种情况。我已经尝试了很多方法来解决这个问题,但一直没有成功。有什么建议么?谢谢。
好问题,+1。查看我的答案,获得完整,简短和简单的解决方案。这是通过复制正确处理属性的唯一答案(当前两个)。而且,即使属于旧名称空间的属性也能正确处理 - 升级到新的名称空间)。 @Gunther在应用于我的答案中使用的XML文档时的答案产生了旧名称空间中不需要的名称空间节点。它也不必要地使用XSLT 2.0。 – 2011-05-08 20:50:04