您的要求可能有点棘手:替换 Document 元素的默认命名空间很简单。但是在 XSLT-1.0 中添加未使用的 xslns:xsi 命名空间需要 EXSLT 扩展和 Michael Kay 在回复 this question 时解释的特殊技术。它涉及在全局变量中创建一个未使用的元素,然后将其命名空间复制到模板中以替换默认命名空间。在 XSLT-2.0 及更高版本中,这会更容易(见下文)。
EXSLT 扩展并非在所有 XSLT-1.0 处理器中都可用。但是有必要从变量中创建一个节点集。
所以所有的命名空间都要在xsl:stylesheet元素中定义,然后根元素(这里是ns0:Document)被一个模板匹配并替换为它的local-name()部分,添加了新的默认命名空间,然后是复制变量中定义的元素的“虚拟”命名空间。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://mydata.com/H2H/Automation" xmlns:urn="urn:iso:std:iso" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ext="http://exslt.org/common">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<!-- identity template (except elements)-->
<xsl:template match="node()[not(self::*)]|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:variable name="nsXSI">
<xsl:element name="xsi:dummy" namespace="http://www.w3.org/2001/XMLSchema-instance" />
</xsl:variable>
<xsl:template match="ns0:*|*">
<xsl:element name="{local-name()}" namespace="urn:iso:std:iso">
<xsl:copy-of select="ext:node-set($nsXSI)/*/namespace::xsi" />
<xsl:apply-templates select="node() | @*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
即使在 XSLT-1.0 中,输出也应该符合预期:
<Document xmlns="urn:iso:std:iso" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrCdtTrfInitn>
<GrpHdr>
</GrpHdr>
</CstmrCdtTrfInitn>
</Document>
简化的解决方案需要支持 XSLT-2.0 的处理器。然后你可以使用xsl:namespace指令如下,不需要“虚拟”变量:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://mydata.com/H2H/Automation">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<!-- identity template (except elements)-->
<xsl:template match="node()[not(self::element())]|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="ns0:*|*">
<xsl:element name="{local-name(.)}" namespace="urn:iso:std:iso">
<xsl:namespace name="xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:namespace>
<xsl:apply-templates select="node() | @*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
输出是一样的。
通过使用 XSLT-3.0+ 的 xsl:mode 将 身份模板 替换为
,可以进一步简化上述 XSLT-2.0 解决方案
<xsl:mode on-no-match="shallow-copy"/>