【发布时间】:2015-12-14 12:31:03
【问题描述】:
我是 xslt 的新手,我收到了一个简单的请求:使用 Xslt(1.0,我不能使用 2.0)将默认 xml 命名空间替换为 xml 文档中的另一个命名空间。
我找到了一种简单的方法,但我仍然有一个我不明白的错误(例如,.Net framework 4.5 中的 XslCompiledTransform 和 Altova Xml Spy 发生这种情况,但 Notepad++ 中的 Xslt 插件不会发生这种情况) :
这是输入 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="urn:old.namespace"。我不明白为什么。
更新:
所以,我的预期结果是:
<?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>
请问,有人可以帮我吗?
【问题讨论】:
-
您正在使用
<xsl:copy>复制范围内的命名空间,您需要将其替换为<xsl:element name="{name()}" namespace="{namespace-uri()}">,但是这样会丢失xmlns:i="http://www.w3.org/2001/XMLSchema-instance"。 -
你追求的结果是什么?
-
我不希望将 urn:old.namespace 设置为 de DateTime 和 OffsetMinutes 节点上的默认命名空间。
-
为什么要为此使用 XSLT?您可以使用简单的字符串操作轻松更改
xmlns=".."声明的内容。 -
你说得对,我就是这么说的。 Xslt 是应用程序需求的一部分,他们可以将它们放在一个文件夹中以动态更改 SOA 应用程序的输出。