Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TCLSOAP & XML namespaces

14 views
Skip to first unread message

GC

unread,
Mar 9, 2006, 4:24:27 PM3/9/06
to
Is there anyway to get TCLSOAP to use a different namespace than "ns"?
I've tried everything I can find but it always shows up as ns.

Thanks!

nichol...@yahoo.com

unread,
Mar 9, 2006, 5:29:11 PM3/9/06
to
If you create your own envelope wrapper proc you can override the
namespace code:


proc EnvelopeWrapper {procVarName args} {
upvar $procVarName procvar

set procName [lindex [split $procVarName {_}] end]
set params $procvar(params)
set name $procvar(name)
set uri $procvar(uri)
set soapenv $procvar(version)
set soapenc $procvar(encoding)

# Check for options (ie: -header) give up on the fist non-matching
arg.
array set opts {-headers {} -attributes {}}
while {[string match -* [lindex $args 0]]} {
switch -glob -- [lindex $args 0] {
-header* {
set opts(-headers) [concat $opts(-headers) [lindex
$args 1]]
set args [lreplace $args 0 0]
}
-attr* {
set opts(-attributes) [concat $opts(-attributes)
[lindex $args 1]]
set args [lreplace $args 0 0]
}
-- {
set args [lreplace $args 0 0]
break
}
default {
# stop option processing at the first invalid option.
break
}
}
set args [lreplace $args 0 0]
}

# check for variable number of params and set the num required.
if {[lindex $params end] == "args"} {
set n_params [expr {( [llength $params] - 1 ) / 2}]
} else {
set n_params [expr {[llength $params] / 2}]
}

# check we have the correct number of parameters supplied.
if {[llength $args] < $n_params} {
set msg "wrong # args: should be \"$procName"
foreach { id type } $params {
append msg " " $id
}
append msg "\""
return -code error $msg
}

set doc [dom::DOMImplementation create]
set envx [dom::document createElement $doc "SOAP-ENV:Envelope"]

dom::element setAttribute $envx "xmlns:SOAP-ENV" $soapenv
dom::element setAttribute $envx "xmlns:SOAP-ENC" $soapenc
dom::element setAttribute $envx "SOAP-ENV:encodingStyle" $soapenc

# The set of namespaces depends upon the SOAP encoding as specified
by
# the encoding option and the user specified set of relevant
schemas.
foreach {nsname url} [concat \
[::rpcvar::default_schemas $soapenc] \
$procvar(schemas)] {
if {! [string match "xmlns:*" $nsname]} {
set nsname "xmlns:$nsname"
}
dom::element setAttribute $envx $nsname $url
}

# Insert the Header elements (if any)
if {$opts(-headers) != {}} {
set headelt [dom::document createElement $envx
"SOAP-ENV:Header"]
foreach {hname hvalue} $opts(-headers) {
set hnode [dom::document createElement $headelt $hname]
::SOAP::insert_value $hnode $hvalue
}
}

# Insert the body element and atributes.
# ########################################################
# Change the else condition below
# #######################################################
set bod [dom::document createElement $envx "SOAP-ENV:Body"]
if {$uri == ""} {
# don't use a namespace prefix if we don't have a namespace.
set cmd [dom::document createElement $bod "$name" ]
} else {
set cmd [dom::document createElement $bod "ns:$name" ]
dom::element setAttribute $cmd "xmlns:ns" $uri
}

# Insert any method attributes
if {$opts(-attributes) != {}} {
foreach {atname atvalue} $opts(-attributes) {
dom::element setAttribute $cmd $atname $atvalue
}
}

# insert the parameters.
set param_no 0
foreach {key type} $params {
set val [lindex $args $param_no]
set d_param [dom::document createElement $cmd $key]
::SOAP::insert_value $d_param [::rpcvar::rpcvar $type $val]
incr param_no
}


# We have to strip out the DOCTYPE element though. It would be
better to
# remove the DOM node for this, but that didn't work.
set prereq [dom::DOMImplementation serialize $doc]
set req {}
dom::DOMImplementation destroy $doc ;# clean up
regsub "<!DOCTYPE\[^>\]*>\r?\n?" $prereq {} req ;# hack

set req [encoding convertto utf-8 $req] ;# make it UTF-8
return $req ;# return the XML
data
}


SOAP::create SomeMethod -proxy
"http://localhost/superSOAP/webcontrol.asmx" \
-action
"http://www.atune.biz/web/services/WC/2006-1/isWebUserAuthenticated" \
-uri "http://www.atune.biz/web/services/WC/2006-01" \
-params {WebUser webUser}

SOAP::configure SomeMethod -wrapProc EnvelopWrapper

GC

unread,
Mar 9, 2006, 7:01:10 PM3/9/06
to
Hi,
Thanks for the response. It seems like that's a lot to do for the end
result I want. Here's the relevant part of the SOAP envelope that I'm
trying to produce:
<SOAP-ENV:Body>
<m:MSLR
xmlns:m="urn:ms">
<m:username>
String
</m:username>
<m:password>
String
</m:password>
</m:MSLR>
</SOAP-ENV:Body>

instead of:

<SOAP-ENV:Body>
<ns:MSLR
xmlns:ns="urn:ms">
<username
xsi:type="xsd:string">
String
</username>
<password
xsi:type="xsd:string">
String
</password>
</ns:MSLR>
</SOAP-ENV:Body>
Notice how everything is preceded with "ns". Is there an easier way to
do what I want? Thanks again!

nichol...@yahoo.com

unread,
Mar 9, 2006, 11:47:29 PM3/9/06
to
The SOAP envelop wrapper procedure above is the default version that
comes with TclSOAP. All, I did was copy and paste. So really all you
need to do is configure your SOAP method to use the wrapper. See the
main TclSOAP web page for an example. Then in the wrapper code above
change this code:

# ########################################################
# Change the else condition below Notice I commented out the ns
namespace.


# #######################################################
set bod [dom::document createElement $envx "SOAP-ENV:Body"]
if {$uri == ""} {
# don't use a namespace prefix if we don't have a namespace.
set cmd [dom::document createElement $bod "$name" ]
} else {

# set cmd [dom::document createElement $bod "ns:$name" ]
# dom::element setAttribute $cmd "xmlns:ns" $uri
}

Adrian Ho

unread,
Mar 10, 2006, 2:25:01 AM3/10/06
to
On 2006-03-10, nichol...@yahoo.com <nichol...@yahoo.com> wrote:
> The SOAP envelop wrapper procedure above is the default version that
> comes with TclSOAP. All, I did was copy and paste. So really all you
> need to do is configure your SOAP method to use the wrapper. See the
> main TclSOAP web page for an example. Then in the wrapper code above
> change this code:
> [...]

An alternative that I like to use when I have actual XML samples
of the SOAP requests is to have the -wrapProc simply substitute the
appropriate values into an XML template. See my comment (as "lexfiend")
in <http://wiki.tcl.tk/1761> for details.

- Adrian

GC

unread,
Mar 10, 2006, 7:35:52 AM3/10/06
to
Guys, thanks for your responses.

Adrian Ho

unread,
Mar 10, 2006, 8:12:45 PM3/10/06
to
On 2006-03-10, Adrian Ho <t...@03s.net> wrote:
> An alternative that I like to use when I have actual XML samples
> of the SOAP requests is to have the -wrapProc simply substitute the
> appropriate values into an XML template. See my comment (as "lexfiend")
> in <http://wiki.tcl.tk/1761> for details.

Scott Nichols correctly pointed out that my code fragment didn't do
XML character-escaping (and perhaps other stuff as well). If anyone's
actually using that code, I've updated it accordingly in the Wiki page.
Do try it and point out anything else I may have missed.

- Adrian

Dan Smart

unread,
Mar 11, 2006, 6:42:57 PM3/11/06
to
On 2006-03-09 19:01:10 -0500, "GC" <gregc...@yahoo.com> said:

> Hi,
> Thanks for the response. It seems like that's a lot to do for the end
> result I want. Here's the relevant part of the SOAP envelope that I'm
> trying to produce:
> <SOAP-ENV:Body>
> <m:MSLR
> xmlns:m="urn:ms">
> <m:username>
> String
> </m:username>
> <m:password>
> String
> </m:password>
> </m:MSLR>
> </SOAP-ENV:Body>
>
> instead of:
>
> <SOAP-ENV:Body>
> <ns:MSLR
> xmlns:ns="urn:ms">
> <username

This should probably be <ns:username


> xsi:type="xsd:string">
> String
> </username>
> <password

This should probably be <ns:password


> xsi:type="xsd:string">
> String
> </password>
> </ns:MSLR>
> </SOAP-ENV:Body>
> Notice how everything is preceded with "ns". Is there an easier way to
> do what I want? Thanks again!

It seems to me that anything that cares that the namespace prefix is
'ns' rather than 'm' is broken, namespace prefixes are not the
namespace identifier, the given urn is the namespace identifier. The
W3C seem to agree with me as well.

I don't think that your problem is really 'ns' rather than 'm', I think
your problem is that in the first instance 'username' and 'password'
are in the specified namespace, whereas in the second they are not.
This is probably what you need to fix.

Dan

nichol...@yahoo.com

unread,
Mar 16, 2006, 11:50:52 AM3/16/06
to
I also had issues with the ns: namespace parameter. I had to comment
this code out. Thanks for your help by the way with my topic post. The
web service that complained about it in my situation was Microsoft IIS
running .NET framwork 2.0. The web service understood the SOAP envelop
once the ns: namespace attributes were removed from the SOAP
parameters. Other wise it retuned some object not defined errors
instead of the desired SOAP response.

Scott

0 new messages