我是xslt的新手,我收到了一个简单的请求:使用Xslt(1.0,我不能使用2.0)将xml文档中的默认xml命名空间替换为另一个命名空间。 / p>
我找到了一种简单的方法,但我仍然有一个我不明白的错误(来自.Net framework 4.5和Altova Xml Spy的XslCompiledTransform,而不是来自的Xslt插件)例如Notepad ++):
这是输入Xml:
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:old.namespace">
<Companies>
<Company>
<AuditedOn xmlns:d4p1="http://schemas.datacontract.org/2004/07/System">
<d4p1:DateTime>2012-10-08T13:34:04.04Z</d4p1:DateTime>
<d4p1:OffsetMinutes>0</d4p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest</Name>
</Company>
<Company>
<AuditedOn xmlns:d6p1="http://schemas.datacontract.org/2004/07/System">
<d6p1:DateTime>2012-10-08T13:34:04.04Z</d6p1:DateTime>
<d6p1:OffsetMinutes>0</d6p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest2</Name>
</Company>
</Companies>
</Test>
我的Xslt:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:previous="urn:old.namespace" >
<xsl:output encoding='UTF-8' indent='yes' method='xml'/>
<xsl:template match='@*|node()'>
<xsl:copy>
<xsl:apply-templates select='@*|node()'/>
</xsl:copy>
</xsl:template>
<!-- Previous namespace -> current. No other changes required. -->
<xsl:template match='previous:*'>
<xsl:element name='{local-name()}'
namespace='urn:new.namespace'>
<xsl:copy-of select='namespace::*[not(. = namespace-uri(current()))]' />
<xsl:apply-templates select='@* | node()' />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
结果:
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="urn:new.namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Companies>
<Company>
<AuditedOn xmlns:d4p1="http://schemas.datacontract.org/2004/07/System">
<d4p1:DateTime xmlns="urn:old.namespace">2012-10-08T13:34:04.04Z</d4p1:DateTime>
<d4p1:OffsetMinutes xmlns="urn:old.namespace">0</d4p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest</Name>
</Company>
<Company>
<AuditedOn xmlns:d6p1="http://schemas.datacontract.org/2004/07/System">
<d6p1:DateTime xmlns="urn:old.namespace">2012-10-08T13:34:04.04Z</d6p1:DateTime>
<d6p1:OffsetMinutes xmlns="urn:old.namespace">0</d6p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest2</Name>
</Company>
</Companies>
</Test>
如您所见,在AuditedOn节点(这是一个DateTimeOffset对象)上,转换集再次设置xmlns =&#34; urn:old.namespace&#34;在每个节点上。我不明白为什么。
更新:
所以,我的预期结果是:
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="urn:new.namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Companies>
<Company>
<AuditedOn xmlns:d4p1="http://schemas.datacontract.org/2004/07/System">
<d4p1:DateTime>2012-10-08T13:34:04.04Z</d4p1:DateTime>
<d4p1:OffsetMinutes>0</d4p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest</Name>
</Company>
<Company>
<AuditedOn xmlns:d6p1="http://schemas.datacontract.org/2004/07/System">
<d6p1:DateTime>2012-10-08T13:34:04.04Z</d6p1:DateTime>
<d6p1:OffsetMinutes>0</d6p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest2</Name>
</Company>
</Companies>
</Test>
拜托,有人可以帮帮我吗?
答案 0 :(得分:1)
我相信这会产生你正在寻找的结果(你忽略了提供):
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:previous="urn:old.namespace">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- old namespace -> new -->
<xsl:template match="previous:*">
<xsl:element name="{local-name()}" namespace="urn:new.namespace">
<xsl:copy-of select="namespace::*[not(. = 'urn:old.namespace')]" />
<xsl:copy-of select="@*" />
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:template>
<!-- instead of identity transform template -->
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="@*" />
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<强>结果强>
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="urn:new.namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Companies>
<Company>
<AuditedOn xmlns:d4p1="http://schemas.datacontract.org/2004/07/System">
<d4p1:DateTime>2012-10-08T13:34:04.04Z</d4p1:DateTime>
<d4p1:OffsetMinutes>0</d4p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest</Name>
</Company>
<Company>
<AuditedOn xmlns:d6p1="http://schemas.datacontract.org/2004/07/System">
<d6p1:DateTime>2012-10-08T13:34:04.04Z</d6p1:DateTime>
<d6p1:OffsetMinutes>0</d6p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest2</Name>
</Company>
</Companies>
</Test>
以上内容可以简化为:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.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>
<!-- old namespace -> new -->
<xsl:template match="*[namespace-uri() = 'urn:old.namespace']">
<xsl:element name="{local-name()}" namespace="urn:new.namespace">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这里的结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="urn:new.namespace">
<Companies>
<Company>
<AuditedOn>
<d4p1:DateTime xmlns:d4p1="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:old.namespace">2012-10-08T13:34:04.04Z</d4p1:DateTime>
<d4p1:OffsetMinutes xmlns:d4p1="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:old.namespace">0</d4p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest</Name>
</Company>
<Company>
<AuditedOn>
<d6p1:DateTime xmlns:d6p1="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:old.namespace">2012-10-08T13:34:04.04Z</d6p1:DateTime>
<d6p1:OffsetMinutes xmlns:d6p1="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:old.namespace">0</d6p1:OffsetMinutes>
</AuditedOn>
<Name>CompanyNameTest2</Name>
</Company>
</Companies>
</Test>
此结果在语义上与另一个结果相同。差异仅仅是装饰性的:
名称空间声明
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
已被移动
并且(不必要地)复制到其他元素 - 但是,这个
声明无论如何都是多余的,所以它在哪里都无所谓
出现,或者如果出现的话;
某些元素将默认命名空间声明为
xmlns="urn:old.namespace"
- 然而,实际上没有元素
放在此命名空间。
同样,您在问题中报告的结果在语义上也与上述两个相同。 xmlns="urn:old.namespace"
的冗余默认命名空间声明就是:冗余。整个结果中的任何节点实际上都没有放在此命名空间中。
使用符合标准的XML解析器解析结果的任何目标应用程序都不应该能够区分这三个结果。