Package suds :: Package umx :: Module core
[hide private]
[frames] | no frames]

Source Code for Module suds.umx.core

  1  # This program is free software; you can redistribute it and/or modify 
  2  # it under the terms of the (LGPL) GNU Lesser General Public License as 
  3  # published by the Free Software Foundation; either version 3 of the  
  4  # License, or (at your option) any later version. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU Library Lesser General Public License for more details at 
 10  # ( http://www.gnu.org/licenses/lgpl.html ). 
 11  # 
 12  # You should have received a copy of the GNU Lesser General Public License 
 13  # along with this program; if not, write to the Free Software 
 14  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 15  # written by: Jeff Ortel ( jortel@redhat.com ) 
 16   
 17  """ 
 18  Provides base classes for XML->object I{unmarshalling}. 
 19  """ 
 20   
 21  from logging import getLogger 
 22  from suds import * 
 23  from suds.umx import * 
 24  from suds.umx.attrlist import AttrList 
 25  from suds.sax.text import Text 
 26  from suds.sudsobject import Factory, merge 
 27   
 28   
 29  log = getLogger(__name__) 
 30   
 31  reserved = { 'class':'cls', 'def':'dfn', } 
 32   
33 -class Core:
34 """ 35 The abstract XML I{node} unmarshaller. This class provides the 36 I{core} unmarshalling functionality. 37 """ 38
39 - def process(self, content):
40 """ 41 Process an object graph representation of the xml I{node}. 42 @param content: The current content being unmarshalled. 43 @type content: L{Content} 44 @return: A suds object. 45 @rtype: L{Object} 46 """ 47 self.reset() 48 return self.append(content)
49
50 - def append(self, content):
51 """ 52 Process the specified node and convert the XML document into 53 a I{suds} L{object}. 54 @param content: The current content being unmarshalled. 55 @type content: L{Content} 56 @return: A I{append-result} tuple as: (L{Object}, I{value}) 57 @rtype: I{append-result} 58 @note: This is not the proper entry point. 59 @see: L{process()} 60 """ 61 self.start(content) 62 self.append_attributes(content) 63 self.append_children(content) 64 self.append_text(content) 65 self.end(content) 66 return self.postprocess(content)
67
68 - def postprocess(self, content):
69 """ 70 Perform final processing of the resulting data structure as follows: 71 - Mixed values (children and text) will have a result of the I{content.node}. 72 - Simi-simple values (attributes, no-children and text) will have a result of a 73 property object. 74 - Simple values (no-attributes, no-children with text nodes) will have a string 75 result equal to the value of the content.node.getText(). 76 @param content: The current content being unmarshalled. 77 @type content: L{Content} 78 @return: The post-processed result. 79 @rtype: I{any} 80 """ 81 node = content.node 82 if len(node.children) and node.hasText(): 83 return node 84 attributes = AttrList(node.attributes) 85 if attributes.rlen() and \ 86 not len(node.children) and \ 87 node.hasText(): 88 p = Factory.property(node.name, node.getText()) 89 return merge(content.data, p) 90 if len(content.data): 91 return content.data 92 lang = attributes.lang() 93 if content.node.isnil(): 94 return None 95 if not len(node.children) and content.text is None: 96 if self.nillable(content): 97 return None 98 else: 99 return Text('', lang=lang) 100 if isinstance(content.text, basestring): 101 return Text(content.text, lang=lang) 102 else: 103 return content.text
104
105 - def append_attributes(self, content):
106 """ 107 Append attribute nodes into L{Content.data}. 108 Attributes in the I{schema} or I{xml} namespaces are skipped. 109 @param content: The current content being unmarshalled. 110 @type content: L{Content} 111 """ 112 attributes = AttrList(content.node.attributes) 113 for attr in attributes.real(): 114 name = attr.name 115 value = attr.value 116 self.append_attribute(name, value, content)
117
118 - def append_attribute(self, name, value, content):
119 """ 120 Append an attribute name/value into L{Content.data}. 121 @param name: The attribute name 122 @type name: basestring 123 @param value: The attribute's value 124 @type value: basestring 125 @param content: The current content being unmarshalled. 126 @type content: L{Content} 127 """ 128 key = name 129 key = '_%s' % reserved.get(key, key) 130 setattr(content.data, key, value)
131
132 - def append_children(self, content):
133 """ 134 Append child nodes into L{Content.data} 135 @param content: The current content being unmarshalled. 136 @type content: L{Content} 137 """ 138 for child in content.node: 139 cont = Content(child) 140 cval = self.append(cont) 141 key = reserved.get(child.name, child.name) 142 if key in content.data: 143 v = getattr(content.data, key) 144 if isinstance(v, list): 145 v.append(cval) 146 else: 147 setattr(content.data, key, [v, cval]) 148 continue 149 if self.unbounded(cont): 150 if cval is None: 151 setattr(content.data, key, []) 152 else: 153 setattr(content.data, key, [cval,]) 154 else: 155 setattr(content.data, key, cval)
156
157 - def append_text(self, content):
158 """ 159 Append text nodes into L{Content.data} 160 @param content: The current content being unmarshalled. 161 @type content: L{Content} 162 """ 163 if content.node.hasText(): 164 content.text = content.node.getText()
165
166 - def reset(self):
167 pass
168
169 - def start(self, content):
170 """ 171 Processing on I{node} has started. Build and return 172 the proper object. 173 @param content: The current content being unmarshalled. 174 @type content: L{Content} 175 @return: A subclass of Object. 176 @rtype: L{Object} 177 """ 178 content.data = Factory.object(content.node.name)
179
180 - def end(self, content):
181 """ 182 Processing on I{node} has ended. 183 @param content: The current content being unmarshalled. 184 @type content: L{Content} 185 """ 186 pass
187
188 - def bounded(self, content):
189 """ 190 Get whether the content is bounded (not a list). 191 @param content: The current content being unmarshalled. 192 @type content: L{Content} 193 @return: True if bounded, else False 194 @rtype: boolean 195 '""" 196 return ( not self.unbounded(content) )
197
198 - def unbounded(self, content):
199 """ 200 Get whether the object is unbounded (a list). 201 @param content: The current content being unmarshalled. 202 @type content: L{Content} 203 @return: True if unbounded, else False 204 @rtype: boolean 205 '""" 206 return False
207
208 - def nillable(self, content):
209 """ 210 Get whether the object is nillable. 211 @param content: The current content being unmarshalled. 212 @type content: L{Content} 213 @return: True if nillable, else False 214 @rtype: boolean 215 '""" 216 return False
217