如何在SOAP请求
问题描述:
我有这样的SOAP请求使用XSL更改命名空间URI:如何在SOAP请求
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<wsse:Security mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>test</wsse:Username>
<wsse:Password>test</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<hel:docTypeRef_tns_sayHello xmlns:hel="http://aaa/bbb.fr">
<arg0>John</arg0>
<arg1>111-222-333</arg1>
</hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>
我想首先要改变出现在HEL空间URI:docTypeRef_tns_sayHello元素别的东西(例如:http://test.fr) 。此命名空间定义可出现在 HEL:docTypeRef_tns_sayHello元件如在上面或在根Envelope元素的代码,所以我想仅在Envelope元素
然后我想修改添加此命名空间定义mustUnderstand属性的属性值0
结果应该是这样的形式:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext- 1.0.xsd"
**xmlns:hel="http://test.fr"**>
<soapenv:Header>
<wsse:Security mustUnderstand="**0**">
<wsse:UsernameToken>
<wsse:Username>test</wsse:Username>
<wsse:Password>test</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<hel:docTypeRef_tns_sayHello>
<arg0>John</arg0>
<arg1>111-222-333</arg1>
</hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>
有人能帮助我吗? 谢谢!
答
一,这是一个通用的,参数化XSLT 1.0解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pElemName" select="'hel:docTypeRef_tns_sayHello'"/>
<xsl:param name="pOldNamespace" select="'http://aaa/bbb.fr'"/>
<xsl:param name="pNewNamespace" select="'http://test.fr'"/>
<xsl:variable name="vPrefix" select="substring-before($pElemName, ':')"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test=
"not(name() = $pElemName
and
namespace-uri() = $pOldNamespace
)
">
<xsl:call-template name="identity"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}" namespace="{$pNewNamespace}">
<xsl:copy-of select=
"namespace::*
[not(name() = $vPrefix
and
. = $pOldNamespace
)
]"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()" mode="removeNS"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="removeNS">
<xsl:choose>
<xsl:when test=
"not(starts-with(name(), $vPrefix)
and
namespace-uri() = $pOldNamespace
)">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select=
"namespace::*
[not(name() = $vPrefix
and
. = $pOldNamespace
)
]"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()" mode="removeNS"/>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="@mustUnderstand">
<xsl:attribute name="{name()}">0</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
当这种转变是在所提供的XML文档应用:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<wsse:Security mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>test</wsse:Username>
<wsse:Password>test</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<hel:docTypeRef_tns_sayHello xmlns:hel="http://aaa/bbb.fr">
<arg0>John</arg0>
<arg1>111-222-333</arg1>
</hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>
想要的,正确的结果产生:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<wsse:Security mustUnderstand="0">
<wsse:UsernameToken>
<wsse:Username>test</wsse:Username>
<wsse:Password>test</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<hel:docTypeRef_tns_sayHello xmlns:hel="http://test.fr">
<arg0>John</arg0>
<arg1>111-222-333</arg1>
</hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>
待办事项:在XSLT 1.0,不可能不使用扩展函数(至少xxx:node-set()
)动态地添加新的命名空间(即不存在作为命名空间节点)给一个元素。在XSLT 2.0中,可以使用新的xsl:namespace
指令从动态(静态未知)部分动态构建新的名称空间节点。
这里是一个小例子,如何用XSLT 1.0在转型命名空间节点开始添加一个新的,不存在的:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:variable name="vrtfDoc">
<t xmlns:hel="http://test.fr"/>
</xsl:variable>
<xsl:variable name="vNS" select=
"ext:node-set($vrtfDoc)/*/namespace::*
[name()='hel']"/>
<xsl:element name="{name()}"
namespace="{namespace-uri()}">
<xsl:copy-of select="namespace::*"/>
<xsl:copy-of select="$vNS"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
当这一转型是这个XML文档施加:
<t xmlns:someNS="some:NS"/>
它与它的所有命名空间节点重新创建顶级元素t
,并增加了一个新的命名空间节点,以它:
<t xmlns:someNS="some:NS" xmlns:hel="http://test.fr"/>
二,这里是一个完整的,XSLT 2.0溶液:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pElemName" select="'hel:docTypeRef_tns_sayHello'"/>
<xsl:param name="pOldNamespace" select="'http://aaa/bbb.fr'"/>
<xsl:param name="pNewNamespace" select="'http://test.fr'"/>
<xsl:variable name="vPrefix" select="substring-before($pElemName, ':')"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:namespace name="{$vPrefix}" select="$pNewNamespace"/>
<xsl:copy-of select=
"namespace::*
[not(name() = $vPrefix
and
. = $pOldNamespace
)
]"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test=
"not(name() = $pElemName
and
namespace-uri() = $pOldNamespace
)
">
<xsl:call-template name="identity"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}" namespace="{$pNewNamespace}">
<xsl:copy-of select=
"namespace::*
[not(name() = $vPrefix
and
. = $pOldNamespace
)
]"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()" mode="removeNS"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="removeNS">
<xsl:choose>
<xsl:when test=
"not(starts-with(name(), $vPrefix)
and
namespace-uri() = $pOldNamespace
)">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select=
"namespace::*
[not(name() = $vPrefix
and
. = $pOldNamespace
)
]"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()" mode="removeNS"/>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="@mustUnderstand">
<xsl:attribute name="{name()}">0</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
当这种转化是在同一个XML文档(以上)施加时,想要的,正确的结果产生:的
<soapenv:Envelope xmlns:hel="http://test.fr"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<wsse:Security mustUnderstand="0">
<wsse:UsernameToken>
<wsse:Username>test</wsse:Username>
<wsse:Password>test</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<hel:docTypeRef_tns_sayHello>
<arg0>John</arg0>
<arg1>111-222-333</arg1>
</hel:docTypeRef_tns_sayHello>
</soapenv:Body>
</soapenv:Envelope>
可能重复[如何更改命名空间](http://stackoverflow.com/questions/6694908/how-to-change-namespace) – newtover 2012-01-15 14:07:41
你是否只使用XSLT 1。0还是可以使用XSLT 2.0?我提供了一个XSLT 1.0解决方案,但是对于命名空间创建需求,需要在通用解决方案中使用扩展函数。在XSLT 2.0中不需要扩展功能。 – 2012-01-15 15:04:22