Changeset 447
- Timestamp:
- 02/20/03 00:58:36 (6 years ago)
- Files:
-
- trunk/RBFoundation/RBFoundation/XMLNode.py (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/RBFoundation/RBFoundation/XMLNode.py
r437 r447 48 48 _any = matchall() 49 49 50 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~51 52 50 class matchobj(object): 53 51 def __init__(self, testcall): … … 60 58 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 61 59 62 class xmlattrmixin(object): 63 def __getattribute__(self, name): 64 """Returns self.attrs[name] when possible. Use explicit self.attrs[name] for more uniform access.""" 65 try: 66 return object.__getattribute__(self, name) 67 except AttributeError: 68 if name in self.attrs: 69 return self.attrs[name] 70 else: raise 71 72 def __setattr__(self, name, value): 73 """Sets self.attrs[name] = value when possible. Use explicit self.attrs[name] for more uniform access.""" 74 try: 75 # This works because of the __slots__ definition 76 object.__setattr__(self, name, value) 77 except AttributeError: 78 if name in self.attrs: 79 self.attrs[name] = str(value) 80 elif not hasattr(self, name): 81 self.attrs[name] = str(value) 82 else: raise 83 84 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 85 86 class xmlnode(object): 60 class xmlnodebase(object): 61 pass 62 63 class xmlnode(xmlnodebase): 87 64 """Simple class to build valid XML. 88 65 Also has some basic access, query, and iteration methods. … … 117 94 __slots__ = ['node', 'prefix', 'namespaces', 'elems', 'attrs', 'nodebuilder', 'softspace'] 118 95 nodebuilder = None 96 default_node = None 119 97 default_attributes = {} 120 98 default_namespaces = XMLNamespaceMap() … … 126 104 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 127 105 128 def __init__(self, node , namespace=None, prefix='', default_namespaces=None, attrlookup=None):106 def __init__(self, node=None, namespace=None, prefix='', default_namespaces=None, attrlookup=None): 129 107 self.enableattrlookup(attrlookup) 130 108 if default_namespaces: self.namespaces = default_namespaces … … 132 110 self.elems = self.default_elements[:] 133 111 self.attrs = self.default_attributes.copy() 134 self.node = node 112 self.node = node or self.default_node or self.__class__.__name__ 135 113 self.namespace = (prefix, namespace) 136 114 self.softspace = 0 # for compatibility with file-like objects … … 246 224 if isinstance(elem, basestring): 247 225 return self.adddata(elem) 248 else: return self.addnode(*elem) 226 elif isinstance(elem, xmlnodebase): 227 # For elements that are prebuilt 228 self.elems.append(elem) 229 return elem 230 else: 231 # For building from tuples and lists 232 return self.addnode(*elem) 249 233 250 234 def setxmlns(self, *args, **kw): … … 295 279 296 280 def enumnodes(self, node=_any, namespace=_any, prefix=_any, idxonly=True): 297 """Returns a generator to iterate through the matching child node indicies of xmlnode""" 281 """Returns a generator to iterate through the matching child node indicies of xmlnode. 282 obj.enumnodes(node=_any, namespace=_any, prefix=_any)""" 283 idxonly = kw.get('idxonly', None) 284 if idxonly is not None: del kw['idxonly'] 285 if args or kw: 286 match = lambda node=_any, namespace=_any, prefix=_any: node == each.node and namespace == each.namespace and prefix == each.prefix 287 else: match = lambda: True 298 288 idx = 0 299 289 for each in self.elems: 300 290 if not isinstance(each, basestring): 301 if node == each.node and namespace == each.namespace and prefix == each.prefix:291 if match(*args, **kw): 302 292 if idxonly: yield idx 303 293 else: yield idx, each 304 294 idx += 1 305 295 306 def iternodes(self, node=_any, namespace=_any, prefix=_any): 307 """Returns a generator to iterate through the matching child nodes of xmlnode""" 296 def iternodes(self, *args, **kw): 297 """Returns a generator to iterate through the matching child nodes of xmlnode. 298 obj.iternodes(node=_any, namespace=_any, prefix=_any)""" 299 if args or kw: 300 match = lambda node=_any, namespace=_any, prefix=_any: node == each.node and namespace == each.namespace and prefix == each.prefix 301 else: match = lambda: True 308 302 for each in self.elems: 309 303 if not isinstance(each, basestring): 310 if node == each.node and namespace == each.namespace and prefix == each.prefix:304 if match(*args, **kw): 311 305 yield each 312 306 … … 433 427 434 428 def _getnodefactory(self, *args, **kw): 435 return self.nodebuilder or self.__class__ 429 nodebuilder = kw.get('nodebuilder', None) 430 if nodebuilder is not None: 431 del kw['nodebuilder'] 432 return nodebuilder, args, kw 433 else: 434 return (self.nodebuilder or self.__class__), args, kw 436 435 437 436 def _makenode(self, *args, **kw): 438 437 kw['default_namespaces'] = self.namespaces.newchain() 439 nodebuilder = self._getnodefactory(*args, **kw)438 nodebuilder, args, kw = self._getnodefactory(*args, **kw) 440 439 result = nodebuilder(*args, **kw) 441 440 return result … … 454 453 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 455 454 455 class xmlattrmixin(object): 456 def __getattribute__(self, name): 457 """Returns self.attrs[name] when possible. Use explicit self.attrs[name] for more uniform access.""" 458 try: 459 return object.__getattribute__(self, name) 460 except AttributeError: 461 if name in self.attrs: 462 return self.attrs[name] 463 else: raise 464 465 def __setattr__(self, name, value): 466 """Sets self.attrs[name] = value when possible. Use explicit self.attrs[name] for more uniform access.""" 467 try: 468 # This works because of the __slots__ definition 469 object.__setattr__(self, name, value) 470 except AttributeError: 471 if name in self.attrs: 472 self.attrs[name] = str(value) 473 elif not hasattr(self, name): 474 self.attrs[name] = str(value) 475 else: raise 476 456 477 class xmlnodeex(xmlnode, xmlattrmixin): 457 478 pass … … 489 510 def _xmlInitComplete(self): pass 490 511 def _xmlGetElement(self): return self 491 def _xmlChildFactory(self, owner, parent, node, attributes, namespacemap):492 return self.__class__493 512 def _toXML(self, *args, **kw): 494 513 return self.toxml() 514 515 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 495 516 496 517 class NodeXMLAdaptor(XMLBuilder.XMLBuilderObjectBase): 497 518 """An external adaptor to bridge between XMLBuilderObjectBase interface and xmlnode""" 498 519 __slots__ = ['result'] 499 500 def __init__(self, owner, parent, node, attributes, namespacemap): 520 nodebuilder = xmlnode 521 522 def __init__(self, owner, parent, node, attributes, namespacemap, nodebuilder=xmlnode): 501 523 prefix = namespacemap.prefix(node[0]) 502 524 if node[0] in namespacemap or not namespacemap.nextmap: 503 525 nodename, xmlns = node[1], node[0] 504 526 else: nodename, xmlns = node[1], None 505 self.result = xmlnode(nodename, xmlns, prefix, default_namespaces=namespacemap) 527 nodebuilder = nodebuilder or self.nodebuilder 528 self.result = nodebuilder(nodename, xmlns, prefix, default_namespaces=namespacemap) 506 529 507 530 for key, value in attributes.iteritems(): … … 522 545 def _xmlGetElement(self): 523 546 return self.result 524 def _xmlChildFactory(self, owner, parent, node, attributes, namespacemap):525 return self.__class__526 547 def _toXML(self, *args, **kw): 527 548 return self.result.toxml() 549 550 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 551 552 class XMLNodeFactory(object): 553 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 554 #~ Constants / Variables / Etc. 555 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 556 557 nodebuilder = xmlnode 558 xmladaptor = NodeXMLAdaptor 559 560 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 561 #~ Public Methods 562 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 563 564 def __init__(self, nodebuilder=None, xmladaptor=None): 565 self.nodebuilder = nodebuilder or self.nodebuilder 566 self.xmladaptor = xmladaptor or self.xmladaptor 567 568 def __call__(self, owner, parent, node, attributes, namespacemap): 569 return self.BuildNode 570 571 def BuildNode(self, *args, **kw): 572 return self.xmladaptor(nodebuilder=self.nodebuilder, *args, **kw) 573 574 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 528 575 529 576 class Producer(XMLBuilder.XMLBuilder):
