Skip to content Skip to sidebar Skip to footer

Suds Generates Empty Elements; How To Remove Them?

[Major Edit based on experience since 1st post two days ago.] I am building a Python SOAP/XML script using Suds, but am struggling to get the code to generate SOAP/XML that is acce

Solution 1:

You can use a plugin to modify the XML before is sent to the server (my answer is based on Ronald Smith's solution):

from suds.plugin import MessagePlugin
from suds.client import Client
import re

classMyPlugin(MessagePlugin):
    defsending(self, context):
        context.envelope = re.sub('\s+<.*?/>', '', context.envelope)


client = Client(URL_WSDL, plugins=[MyPlugin()])

Citing the documentation:

The MessagePlugin currently has (5) hooks :: (...) sending() Provides the plugin with the opportunity to inspect/modify the message text before it is sent.

Basically Suds will call sending before the XML is sent, so you can modify the generated XML (contained in context.envelope). You have to pass the plugin class MyPlugin to the Client constructor for this to work.

Edit

Another way is to use marshalled to modify the XML structure, removing the empty elements (untested code):

classMyPlugin(MessagePlugin):defmarshalled(self, context):
        #remove empty tags inside the Body element#context.envelope[0] is the SOAP-ENV:Header element
        context.envelope[1].prune()

Solution 2:

There's an even easier way - no need for any Reg Ex or exciting iterators ;)

First, define the plugin:

classPrunePlugin(MessagePlugin):defmarshalled(self, context):
        context.envelope = context.envelope.prune()

Then use it when creating the client:

client = Client(url, plugins=[PrunePlugin()])

The prune() method will remove any empty nodes, as documented here: http://jortel.fedorapeople.org/suds/doc/suds.sax.element.Element-class.html

Solution 3:

The Suds factory method generates a regular Python object with regular python attributes that map to the WSDL type definition.

You can use the 'del' builtin function to remove attributes.

>>> order_details = c.factory.create('ns2:OrderDetails')
>>> order_details
(OrderDetails){
   Amount = None
   CurrencyCode = None
   OrderChannelType =
      (OrderChannelType){
         value = None
      }
   OrderDeliveryType =
      (OrderDeliveryType){
         value = None
      }
   OrderLines =
      (ArrayOfOrderLine){
         OrderLine[] = <empty>
      }
   OrderNo = None
   TotalOrderValue = None
 }
>>> del order_details.OrderLines
>>> del order_details.OrderDeliveryType
>>> del order_details.OrderChannelType
>>> order_details
(OrderDetails){
   Amount = None
   CurrencyCode = None
   OrderNo = None
   TotalOrderValue = None
 }

Solution 4:

You can filter the empty elements out with a regular expression.

Assuming your XML data is in the string xmltext;

importrefilteredtext= re.sub('\s+<.*?/>', '', xmltext)

Solution 5:

What do you think of the following MonkeyPatch to skip complex types with a None value?

from suds.mx.literal import Typed
old_skip = Typed.skip
defnew_skip(self, content):
    x = old_skip(self, content)
    ifnot x andgetattr(content.value, 'value', False) isNone:
        x = Truereturn x
Typed.skip = new_skip

Post a Comment for "Suds Generates Empty Elements; How To Remove Them?"