# Adding soap element attributes

**URL:** <https://rubytalk.org/t/adding-soap-element-attributes/32414>\
**Category:** ruby-talk\
**Created:** [27 October 2006 16:43 UTC](https://rubytalk.org/t/adding-soap-element-attributes/32414 "2006-10-27T16:43:07Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andrew\_Tongen](https://avatars.discourse-cdn.com/v4/letter/a/c77e96/32.png) [@Andrew\_Tongen](https://rubytalk.org/u/Andrew_Tongen)\
**Post date:** [27 October 2006 16:43 UTC](https://rubytalk.org/t/adding-soap-element-attributes/32414/1 "2006-10-27T16:43:07Z")

</div>

Hi,

I have a question that I hope will be simple for someone to answer.

I am using soap4r to write a simple library to consume web services from  
an application. The application does not include a WSDL document, so I  
have to write everything by hand.

The application requires attributes in certain elements of the soap  
request, and I am having a little trouble figuring out how to do this.  
So far, a portion of my test code looks like this:

driver = SOAP::RPC::Driver.new(endpoint, 'urn:namespace')  
driver.add\_method\_as('get\_account', 'GetAccountRequest', 'account')  
get\_account = driver.get\_account('user@example.com')

which produces this:

\<n2:GetAccountRequest xmlns:n2="urn:namespace"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env:encodingStyle="[http://schemas.xmlsoap.org/soap/encoding/](http://schemas.xmlsoap.org/soap/encoding/)"\>  
&nbsp;&nbsp;\<account xsi:type="xsd:string"\>[user@example.com](mailto:user@example.com)\</account\>  
\</n2:GetAccountRequest\>

but I need the soap request to look like this:

\<n2:GetAccountRequest xmlns:n2="urn:namespace"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env:encodingStyle="[http://schemas.xmlsoap.org/soap/encoding/](http://schemas.xmlsoap.org/soap/encoding/)"\>  
&nbsp;&nbsp;\<account by="name" xsi:type="xsd:string"\>[user@example.com](mailto:user@example.com)\</account\>  
\</n2:GetAccountRequest\>

with the by="name" attribute in the account element.

I've been experimenting with SOAP::Mapping::Registry to achieve this,  
but I am not sure how it would be done, or even if this is the correct  
approach to take. If anyone can offer any assistance, it would be  
appreciated.

Thanks,  
Andrew

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![NAKAMURA\_Hiroshi4](https://avatars.discourse-cdn.com/v4/letter/n/3ab097/32.png) [@NAKAMURA\_Hiroshi4](https://rubytalk.org/u/NAKAMURA_Hiroshi4)\
**Post date:** [29 October 2006 11:40 UTC](https://rubytalk.org/t/adding-soap-element-attributes/32414/2 "2006-10-29T11:40:07Z")

</div>

Hi,

Andrew Tongen wrote:

> I am using soap4r to write a simple library to consume web services from  
> an application. The application does not include a WSDL document, so I  
> have to write everything by hand.

Unlucky.

> The application requires attributes in certain elements of the soap  
> request, and I am having a little trouble figuring out how to do this.  
> So far, a portion of my test code looks like this:
> 
> driver = SOAP::RPC::Driver.new(endpoint, 'urn:namespace')  
> driver.add\_method\_as('get\_account', 'GetAccountRequest', 'account')  
> get\_account = driver.get\_account('user@example.com')

You need to set up a request object by yourself.

&nbsp;&nbsp;ele = SOAP::SOAPString.new('user@example.com')  
&nbsp;&nbsp;ele.elename = XSD::QName.new(nil, 'account')  
&nbsp;&nbsp;ele.extraattr[XSD::QName.new(nil, 'by')] = 'name'  
&nbsp;&nbsp;driver.get\_account(ele)

It must be a hard work when it comes to a complex request object. You  
can write a WSDL from service definition first.

Regards,  
// NaHi

---

<div class="post-metadata">

**Author:** ![Andrew\_Tongen](https://avatars.discourse-cdn.com/v4/letter/a/c77e96/32.png) [@Andrew\_Tongen](https://rubytalk.org/u/Andrew_Tongen)\
**Post date:** [31 October 2006 16:35 UTC](https://rubytalk.org/t/adding-soap-element-attributes/32414/3 "2006-10-31T16:35:55Z")

</div>

Thanks Hiroshi, that got me started. Soap4r is great, I just wish this  
app had a WSDL!

I may consider writing a WSDL for this application, but for now I only  
need a subset of fucntionality. The request objects are all pretty  
simple, but I am having trouble accessing data from the response  
objects.

After calling:

get\_account = driver.get\_account('user@example.com')

The raw XML response for this command looks something like this:

\<GetAccountResponse xmlns:ns0="urn:namespace"\>  
&nbsp;&nbsp;\<account [name="user@example.com](mailto:name=%22user@example.com)"  
id="770316d9-qwe4-38eu-s84h-2dfe3c6cc874"\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<a n="key1"\>value1\</a\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<a n="key2"\>value2\</a\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<a n="key3"\>value3\</a\>  
&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;\</account\>  
\</GetAccountResponse\>

I need to access the key/value pairs in the a attributes, but  
get\_account.account.a simply returns an array of [value1, value2,  
value3, ...] and seems to ignore the attributes. Many response objects  
for this app take this form, so it would be nice to be able to create a  
hash, or ruby object dynamically based on the key/values.

Can I access the raw response XML somehow, or is there a better way to  
do this?

The app I am using is Zimbra, in case anyone has any experience or  
advice for use with Soap4r.

Thanks again,  
Andrew

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![NAKAMURA\_Hiroshi4](https://avatars.discourse-cdn.com/v4/letter/n/3ab097/32.png) [@NAKAMURA\_Hiroshi4](https://rubytalk.org/u/NAKAMURA_Hiroshi4)\
**Post date:** [4 November 2006 01:51 UTC](https://rubytalk.org/t/adding-soap-element-attributes/32414/4 "2006-11-04T01:51:05Z")

</div>

Hi,

Andrew Tongen wrote:

> I may consider writing a WSDL for this application, but for now I only  
> need a subset of fucntionality. The request objects are all pretty  
> simple, but I am having trouble accessing data from the response  
> objects.
> 
> After calling:
> 
> get\_account = driver.get\_account('user@example.com')
> 
> The raw XML response for this command looks something like this:
> 
> \<GetAccountResponse xmlns:ns0="urn:namespace"\>  
> &nbsp;&nbsp;\<account name="user@example.com"  
> id="770316d9-qwe4-38eu-s84h-2dfe3c6cc874"\>  
> &nbsp;&nbsp;&nbsp;&nbsp;\<a n="key1"\>value1\</a\>  
> &nbsp;&nbsp;&nbsp;&nbsp;\<a n="key2"\>value2\</a\>  
> &nbsp;&nbsp;&nbsp;&nbsp;\<a n="key3"\>value3\</a\>  
> &nbsp;&nbsp;&nbsp;&nbsp;...  
> &nbsp;&nbsp;\</account\>  
> \</GetAccountResponse\>
> 
> I need to access the key/value pairs in the a attributes, but  
> get\_account.account.a simply returns an array of [value1, value2,  
> value3, ...] and seems to ignore the attributes. Many response objects  
> for this app take this form, so it would be nice to be able to create a  
> hash, or ruby object dynamically based on the key/values.

You need to define the service as a document service when you want to  
handle XML attribute. Try the following.

&nbsp;&nbsp;/ / /

require 'soap/rpc/driver'

ns = 'urn:namespace'  
soapaction = nil

driver = SOAP::RPC::Driver.new(nil, ns)  
driver.add\_document\_method('get\_account', soapaction,  
&nbsp;&nbsp;XSD::QName.new(ns, 'GetAccountRequest'),  
&nbsp;&nbsp;XSD::QName.new(ns, 'GetAccountResponse'))

driver.test\_loopback\_response \<\< \<\<\_\_XML\_\_  
\<env:Envelope xmlns:env="[Error](http://schemas.xmlsoap.org/soap/envelope/&quot;&gt);  
&nbsp;&nbsp;\<env:Body\>  
&nbsp;&nbsp;&nbsp;&nbsp;\<GetAccountResponse xmlns:ns0="urn:namespace"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<account name="user@example.com"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id="770316d9-qwe4-38eu-s84h-2dfe3c6cc874"\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<a n="key1"\>value1\</a\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<a n="key2"\>value2\</a\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<a n="key3"\>value3\</a\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</account\>  
&nbsp;&nbsp;&nbsp;&nbsp;\</GetAccountResponse\>  
&nbsp;&nbsp;\</env:Body\>  
\</env:Envelope\>  
\_\_XML\_\_  
driver.wiredump\_dev = STDOUT

ele = SOAP::SOAPString.new('user@example.com')  
ele.elename = XSD::QName.new(nil, 'account')  
ele.extraattr[XSD::QName.new(nil, 'by')] = 'name'  
# !!! a wrapper element is needed for document service.  
req = SOAP::SOAPElement.new(XSD::QName.new(ns, 'GetAccountRequest'))  
req.add(ele)

get\_account = driver.get\_account(req)  
map = {}  
get\_account.account.a.each do |value|  
&nbsp;&nbsp;map[value.xmlattr\_n] = value  
end  
p map # =\> {"key1"=\>"value1", "key2"=\>"value2", "key3"=\>"value3"}

# Now you want to write WSDL, don't you? 🙂

> The app I am using is Zimbra, in case anyone has any experience or  
> advice for use with Soap4r.

Please let me know if you succeeded to use it. Users must be interested  
in it.

Regards,  
// NaHi
