如何使用XSLT为XML根节点添加xmlns:xsi与xsi:noNamespaceSchemaLocation属性?
为XML根节点添加XSI命名空间及Schema定位属性的XSLT解决方案
需求说明
- 给XML根节点添加两个属性:
xmlns:xsi,值为http://www.w3.org/2001/XMLSchema-instancexsi:noNamespaceSchemaLocation,值为mySchema.xsd
输入XML示例
<Root> <Client>mode</Client> </Root>
(注:原输入中的<Client>mode/Client>应为笔误,已修正为正确闭合标签)
期望输出XML示例
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mySchema.xsd"> <Client>mode</Client> </Root>
最初尝试的代码及问题
你最初写的XSLT代码只成功加上了xmlns:xsi属性,xsi:noNamespaceSchemaLocation没生效:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0"> <xsl:strip-space elements="*"/> <xsl:template match="/*"> <xsl:element name="{local-name()}" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mySchema.xsd"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:transform>
执行后输出结果:
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Client>mode</Client> </Root>
你询问的后续方案
你后来写了这段匹配/Root节点的代码,问是否可行:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0"> <xsl:strip-space elements="*"/> <xsl:template match="/Root"> <Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mySchema.xsd"> <xsl:apply-templates select="@*|node()"/> </Root> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:transform>
解答
最初代码失效原因
在XSLT 1.0里,用<xsl:element>创建元素时,直接在标签上写带命名空间前缀的属性(比如xsi:noNamespaceSchemaLocation)不会被正确处理。因为<xsl:element>的属性需要通过<xsl:attribute>显式添加,或者提前在样式表中绑定对应的命名空间。
后续方案的可行性
你写的这段匹配/Root的代码完全可行,执行后会生成符合预期的输出。因为直接用字面量<Root>标签声明命名空间和带前缀的属性时,XSLT处理器能正确解析命名空间绑定,把两个属性都加到根节点上。
更通用的适配方案(支持任意根节点)
如果需要代码能适配任意名称的根节点(不局限于Root),可以修改最初的代码,通过<xsl:attribute>显式添加属性,同时在样式表头部绑定xsi命名空间:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> <xsl:strip-space elements="*"/> <xsl:template match="/*"> <xsl:copy> <!-- 添加上命名空间属性 --> <xsl:attribute name="xmlns:xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute> <!-- 用绑定的xsi前缀添加Schema定位属性 --> <xsl:attribute name="xsi:noNamespaceSchemaLocation">mySchema.xsd</xsl:attribute> <!-- 复制原节点的所有属性和子节点 --> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:transform>
这个版本不管根节点叫什么名字,都能正确添加两个目标属性,通用性更强。
内容的提问来源于stack exchange,提问作者mode
相关产品推荐
相关产品推荐

