2014-05-12 6 views
2

У меня есть SOAP API, и я пытаюсь вызвать метод с помощью мыльной пены (Python):Как получить пенообразование для отправки необязательных, пустых элементов?

DoSomething(ns1:DoSomethingRequest Input,) 

DoSomethingRequest выглядит примерно так:

(DoSomethingRequest){ 
    Person = 
     (Person){ 
     Name = "Joe" 
     Age = 32 
     } 
    ActionOne = None 
    ActionTwo = None 
    ActionThree = None 
} 

В определении типа, то Params действия все они являются необязательными. Чтобы вызвать конкретное действие, вы устанавливаете DoSomethingRequest.ActionOne = [an instance of ActionOneRequest]. Все это нормально (я могу выполнить ActionOne), за исключением того, что я пытаюсь позвонить ActionThree, а ActionThreeRequest - пустой сложный элемент. Когда я установил DoSomethingRequest.ActionThree = ActionThreeRequest, печать на DoSomethingRequest дает:

(DoSomethingRequest){ 
    Person = 
     (Person){ 
     Name = "Joe" 
     Age = 32 
     } 
    ActionOne = None 
    ActionTwo = None 
    ActionThree = <empty> 
} 

и X отправляются на сервер исключает ActionThree. Если я перехватываю код с помощью pdb и добавляю пустой элемент <ActionThree></ActionThree>, он работает.

Глядя на код, для мыльной пены:

 
class ObjectAppender(Appender): 
    """ 
    An L{Object} appender. 
    """ 

    def append(self, parent, content): 
     object = content.value 
     if self.optional(content) and footprint(object) == 0: 
      return 
     child = self.node(content) 
     parent.append(child) 
     for item in object: 
      cont = Content(tag=item[0], value=item[1]) 
      Appender.append(self, child, cont) 

и

 
def footprint(sobject): 
    """ 
    Get the I{virtual footprint} of the object. 
    This is really a count of the attributes in the branch with a significant value. 
    @param sobject: A suds object. 
    @type sobject: L{Object} 
    @return: The branch footprint. 
    @rtype: int 
    """ 
    n = 0 
    for a in sobject.__keylist__: 
     v = getattr(sobject, a) 
     if v is None: continue 
     if isinstance(v, Object): 
      n += footprint(v) 
      continue 
     if hasattr(v, '__len__'): 
      if len(v): n += 1 
      continue 
     n +=1 
    return n 

Я не использую SOAP часто, поэтому я предполагаю, что я либо с помощью API неправильно, или я использую пена неправильно. Или, может быть, API сервиса нестандартен.

Знаете ли вы, почему существует проблема и как лучше всего ее решить?

Странно, обратный вопрос на SO: Suds generates empty elements; how to remove them? К сожалению, удалить пустые элементы намного проще, чем выяснить, какие элементы были удалены и повторно добавить.

Спасибо!

ответ

2

После прочтения спецификаций и бесед с экспертами я не видел ничего, что указывало бы на то, что для SOAP-библиотеки можно исключить необязательные, пустые элементы.

Существует исправленная версия пены на github.

1

В случае, если кто-то другой сталкивается с этим вопросом и не находит ответа. Аналогичная ситуация произошла со мной. Я пытался отправить следующее тело запроса SOAP,

<ns0:list><ns0:filter xsi:type="ns0:UserFilter"/></ns0:list> 

Моей первую попытку, я создал элемент с помощью suds.client.factory и отправить, что ни с чем сконфигурировано. Это привело к следующему телу,

<ns0:list><filter/></ns0:list> 

Затем я попытался создания Element вручную и установка атрибута type вручную. Это достало мне ту же оболочку.

После обработки исходного кода я выяснил, что метод SoapClient.send() лишил мой атрибут в методе sax.Document.plain().

Посмотрев на код, я понял, что могу установить опцию prettyxml=True на клиенте suds, и это не приведет к стиранию атрибута.