调整XML中命名空间位置,请求正确XSLT实现方案
问题:将命名空间
urn:teams:2从<Events>元素转移至<Event>元素 需求说明
需将XML中的命名空间urn:teams:2从<Events>元素转移至其子元素<Event>上。
源XML
<Message xmlns="urn:teams:1"> <Header> <Source>center</Source> </Header> <row> <Events xmlns="urn:teams:2"> <Event> <createdDateTime>2023-01-06T09:42:11-06:00</createdDateTime> <name>Houston</name> <Details> <value>serial number 327</value> </Details> </Event> </Events> </row> </Message>
目标XML
<Message xmlns="urn:teams:1"> <Header> <Source>center</Source> </Header> <row> <Events> <Event xmlns="urn:teams:2"> <createdDateTime>2023-01-06T09:42:11-06:00</createdDateTime> <name>Houston</name> <Details> <value>serial number 327</value> </Details> </Event> </Events> </row> </Message>
尝试过的XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="urn:teams:1" xmlns:ns1="urn:teams:2"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="*" > <xsl:element name="{local-name()}" namespace="urn:teams:1"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> <xsl:template match="/ns0:Message/ns0:row/ns0:Events/ns1:Event"> <xsl:element name="Event" xmlns="urn:teams:2"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> </xsl:stylesheet>
正确的XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="urn:teams:2"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <!-- 默认复制所有节点的身份模板 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 移除<Events>元素上的urn:teams:2命名空间 --> <xsl:template match="ns1:Events"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> <!-- 给<Event>元素添加urn:teams:2命名空间 --> <xsl:template match="ns1:Events/ns1:Event"> <xsl:element name="{local-name()}" namespace="urn:teams:2"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> </xsl:stylesheet>
说明
你之前的XSLT存在两个核心问题:
- 匹配
*的模板优先级高于身份模板,会强制所有元素归属urn:teams:1命名空间,打乱了原有命名空间逻辑; - 路径匹配
/ns0:Message/ns0:row/ns0:Events/ns1:Event错误,源XML中<Events>本身属于urn:teams:2(即ns1前缀),而非ns0,导致目标模板无法匹配到对应元素。
上述正确XSLT通过以下逻辑实现需求:
- 用身份模板保留大部分节点的原始结构与属性;
- 专门匹配带有
urn:teams:2命名空间的<Events>元素,重新生成无命名空间的<Events>; - 匹配
<Events>下的<Event>元素,为其添加urn:teams:2命名空间,完成命名空间声明的转移。
内容的提问来源于stack exchange,提问作者PI2004
相关产品推荐
相关产品推荐

