如何用XSLT 1.0转换XML,为ServiceResponse而非Envelope添加命名空间
解决XSLT 1.0中命名空间错误跑到
<soap:Envelope>的问题 我猜你是在转换SOAP响应的时候踩了命名空间的坑——本来该属于<ServiceResponse>的http://www.scym.com/abcd/dmb/Service/v1命名空间,结果莫名其妙跑到外层的<soap:Envelope>上了,对吧?这大概率是因为你的XSLT没明确控制命名空间的输出位置,或者不小心在根元素上错误继承了目标命名空间。
下面给你一个能精准解决这个问题的XSLT 1.0示例,咱们一步步来:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:svc="http://www.scym.com/abcd/dmb/Service/v1" exclude-result-prefixes="svc"> <!-- 复制SOAP信封结构,明确保留soap命名空间 --> <xsl:template match="/soap:Envelope"> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <xsl:apply-templates select="soap:Body"/> </soap:Envelope> </xsl:template> <!-- 处理SOAP Body,传递子元素的转换逻辑 --> <xsl:template match="soap:Body"> <soap:Body> <xsl:apply-templates select="svc:ServiceResponse"/> </soap:Body> </xsl:template> <!-- 关键:给ServiceResponse明确加上目标命名空间 --> <xsl:template match="svc:ServiceResponse"> <ServiceResponse xmlns="http://www.scym.com/abcd/dmb/Service/v1"> <xsl:apply-templates select="@* | node()"/> </ServiceResponse> </xsl:template> <!-- 默认模板:自动复制所有属性和子元素,保证内容完整 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
重点说明几个关键细节:
- 开头我们在XSLT根元素里声明了两个命名空间:
soap对应源文档的SOAP信封,svc对应ServiceResponse的命名空间,exclude-result-prefixes="svc"能避免这个前缀乱跑到输出的其他元素上。 - 匹配
<soap:Envelope>的模板里,我们显式重新写了soap命名空间的声明,这样输出的信封就只会带自己的命名空间,不会被其他命名空间污染。 - 处理
<ServiceResponse>的模板是核心:我们直接创建了带目标命名空间的<ServiceResponse>元素,这样命名空间就会乖乖出现在这个元素上,而不是外层的信封。 - 默认模板会自动复制所有子元素和属性,比如
<RelatedCFR>、<NUMBER>这些内容都能完整保留,不用额外写模板处理。
如果你的XSLT之前有设置xsl:output indent="yes"来格式化输出,完全可以保留,不影响命名空间的处理。
内容的提问来源于stack exchange,提问作者Vinu
相关产品推荐
相关产品推荐

