提问人:Adnan Maqbool 提问时间:2/15/2021 最后编辑:zx485Adnan Maqbool 更新时间:2/15/2021 访问量:492
XSLT 替换命名空间并添加新的(未使用的)命名空间
XSLT to replace a namespace and also add a new (unused) namespace
问:
我想替换以下 XML 文档的命名空间
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Document xmlns:ns0="http://mydata.com/H2H/Automation">
<CstmrCdtTrfInitn>
<GrpHdr>
</GrpHdr>
</CstmrCdtTrfInitn>
</ns0:Document>
具有以下内容
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrCdtTrfInitn>
<GrpHdr>
</GrpHdr>
</CstmrCdtTrfInitn>
</Document>
关于可以转换的XSLT的任何想法?
我尝试了以下 XSL,但它正在添加带有第二个节点的命名空间,并且也无法删除第一个命名空间。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<xsl:element name="{local-name()}" namespace="http://www.w3.org/2001/XMLSchema-instance">
<xsl:copy-of select="./*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
答:
0赞
zx485
2/15/2021
#1
您的要求可能有点棘手:替换元素的默认命名空间很简单。但是在 XSLT-1.0 中添加未使用的命名空间需要 EXSLT 扩展和 Michael Kay 在回答这个问题时解释的特殊技术。它涉及在全局变量中创建一个未使用的元素,然后将该元素的命名空间复制到模板中,以替换默认命名空间。在 XSLT-2.0 及更高版本中,这会更容易(见下文)。Document
xslns:xsi
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 指令,并且不需要“dummy”变量:
<?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
<xsl:mode on-no-match="shallow-copy"/>
评论
0赞
Adnan Maqbool
2/15/2021
感谢您的快速回复。它给了我错误 sapximapping:nsfinal.xsl:第 6 行:解析 XPath 表达式 'node()[not(self::element()]|@*' 时出错
0赞
zx485
2/15/2021
你是对的。我必须添加一个名为 EXSLT 的外部库才能使 XSLT-1.0 答案正常工作,并将 .element()
*
0赞
Adnan Maqbool
2/15/2021
对不起,我应该得到,我应该更改上述解决方案中的任何内容。
0赞
zx485
2/15/2021
是的。我更改了 XSLT。您还需要 EXSLT 扩展才能使用 XSLT-1.0 解决方案。如果您没有可用的它,您将被困在 XSLT-2.0 或更高版本。
0赞
Adnan Maqbool
2/15/2021
谢谢,修改后的版本在某种程度上有效,但它添加了 urn:iso:std:iso 与所有父节点 ns1 ns2 ns3
0赞
michael.hor257k
2/15/2021
#2
有没有理由你不能简单地做:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://mydata.com/H2H/Automation"
exclude-result-prefixes="ns0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="urn:iso:std:iso">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="/ns0:Document">
<Document xmlns="urn:iso:std:iso" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates/>
</Document>
</xsl:template>
</xsl:stylesheet>
评论