XSLT 1.0生成多默认命名空间XML遇xmlns=""问题求助
多默认命名空间XML生成问题:xmlns="" 成因与简洁解决方案
一、xmlns="" 出现的原因
XSLT 1.0中,模板直接生成的元素默认处于空命名空间。当这些元素被插入到带有默认命名空间的父元素下时,父元素的默认命名空间会被子元素继承,但模板生成的<OrgId>、<Volume>等元素本不属于父元素的默认命名空间(如http://b.example.com或http://c.example.com),因此处理器会自动添加xmlns=""来显式重置命名空间,确保这些元素实际处于空命名空间——这就是输出中出现多余空命名空间声明、导致无法通过XSD验证的原因。
比如<Header>的默认命名空间是http://b.example.com,<Fr>继承了这个空间,但模板生成的<OrgId>属于空命名空间,处理器必须添加xmlns=""来明确它不属于http://b.example.com。
二、简洁实现方案
无需传递命名空间参数或使用带前缀的命名空间,直接在模板生成的目标元素上声明对应的默认命名空间,让元素直接归属到父元素所在的命名空间即可。
优化后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <Root xmlns="http://a.example.com"> <Header xmlns="http://b.example.com"> <Fr> <xsl:apply-templates select="/Trades"> <xsl:with-param name="Id">hello</xsl:with-param> </xsl:apply-templates> </Fr> <To> <xsl:apply-templates select="/Trades"> <xsl:with-param name="Id">goodbye</xsl:with-param> </xsl:apply-templates> </To> </Header> <Body xmlns="http://c.example.com"> <Trades> <xsl:apply-templates select="/Trades/Trade" /> </Trades> </Body> </Root> </xsl:template> <!-- 生成http://b.example.com命名空间下的OrgId/Id --> <xsl:template match="/Trades"> <xsl:param name="Id" /> <OrgId xmlns="http://b.example.com"> <Id> <xsl:value-of select="$Id"/> </Id> </OrgId> </xsl:template> <!-- 生成http://c.example.com命名空间下的Volume/Price --> <xsl:template match="Trade"> <Volume xmlns="http://c.example.com"> <xsl:value-of select="volume"/> </Volume> <Price xmlns="http://c.example.com"> <xsl:value-of select="price"/> </Price> </xsl:template> </xsl:stylesheet>
输出结果(无xmlns="")
<?xml version="1.0" encoding="utf-8"?> <Root xmlns="http://a.example.com"> <Header xmlns="http://b.example.com"> <Fr> <OrgId> <Id>hello</Id> </OrgId> </Fr> <To> <OrgId> <Id>goodbye</Id> </OrgId> </To> </Header> <Body xmlns="http://c.example.com"> <Trades> <Volume>2</Volume> <Price>3</Price> </Trades> </Body> </Root>
可选:用xsl:element动态指定命名空间(适合复用场景)
如果需要统一管理命名空间,可在样式表开头声明命名空间前缀,再用<xsl:element>指定命名空间:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b="http://b.example.com" xmlns:c="http://c.example.com"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <Root xmlns="http://a.example.com"> <Header xmlns="http://b.example.com"> <Fr> <xsl:apply-templates select="/Trades"> <xsl:with-param name="Id">hello</xsl:with-param> </xsl:apply-templates> </Fr> <To> <xsl:apply-templates select="/Trades"> <xsl:with-param name="Id">goodbye</xsl:with-param> </xsl:apply-templates> </To> </Header> <Body xmlns="http://c.example.com"> <Trades> <xsl:apply-templates select="/Trades/Trade" /> </Trades> </Body> </Root> </xsl:template> <xsl:template match="/Trades"> <xsl:param name="Id" /> <xsl:element name="OrgId" namespace="http://b.example.com"> <xsl:element name="Id" namespace="http://b.example.com"> <xsl:value-of select="$Id"/> </xsl:element> </xsl:element> </xsl:template> <xsl:template match="Trade"> <xsl:element name="Volume" namespace="http://c.example.com"> <xsl:value-of select="volume"/> </xsl:element> <xsl:element name="Price" namespace="http://c.example.com"> <xsl:value-of select="price"/> </xsl:element> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者wavydavy
相关产品推荐
相关产品推荐

