1   
   2   
   3   
   4   
   5   
   6   
   7   
   8   
   9   
  10   
  11   
  12   
  13   
  14   
  15   
  16   
  17  """ 
  18  Provides XML I{element} classes. 
  19  """ 
  20   
  21  from logging import getLogger 
  22  from suds import * 
  23  from suds.sax import * 
  24  from suds.sax.text import Text 
  25  from suds.sax.attribute import Attribute 
  26  import sys  
  27  if sys.version_info < (2, 4, 0):  
  28      from sets import Set as set  
  29      del sys  
  30   
  31  log = getLogger(__name__) 
  34      """ 
  35      An XML element object. 
  36      @ivar parent: The node containing this attribute 
  37      @type parent: L{Element} 
  38      @ivar prefix: The I{optional} namespace prefix. 
  39      @type prefix: basestring 
  40      @ivar name: The I{unqualified} name of the attribute 
  41      @type name: basestring 
  42      @ivar expns: An explicit namespace (xmlns="..."). 
  43      @type expns: (I{prefix}, I{name}) 
  44      @ivar nsprefixes: A mapping of prefixes to namespaces. 
  45      @type nsprefixes: dict 
  46      @ivar attributes: A list of XML attributes. 
  47      @type attributes: [I{Attribute},] 
  48      @ivar text: The element's I{text} content. 
  49      @type text: basestring 
  50      @ivar children: A list of child elements. 
  51      @type children: [I{Element},] 
  52      @cvar matcher: A collection of I{lambda} for string matching. 
  53      @cvar specialprefixes: A dictionary of builtin-special prefixes. 
  54      """ 
  55   
  56      matcher = \ 
  57      { 
  58          'eq': lambda a,b: a == b, 
  59          'startswith' : lambda a,b: a.startswith(b), 
  60          'endswith' : lambda a,b: a.endswith(b), 
  61          'contains' : lambda a,b: b in a  
  62      } 
  63       
  64      specialprefixes = { Namespace.xmlns[0] : Namespace.xmlns[1]  } 
  65       
  66      @classmethod 
  68          """ 
  69          Build the specifed pat as a/b/c where missing intermediate nodes are built 
  70          automatically. 
  71          @param parent: A parent element on which the path is built. 
  72          @type parent: I{Element} 
  73          @param path: A simple path separated by (/). 
  74          @type path: basestring 
  75          @return: The leaf node of I{path}. 
  76          @rtype: L{Element} 
  77          """ 
  78          for tag in path.split('/'): 
  79              child = parent.getChild(tag) 
  80              if child is None: 
  81                  child = Element(tag, parent) 
  82              parent = child 
  83          return child 
   84   
  85 -    def __init__(self, name, parent=None, ns=None): 
   86          """ 
  87          @param name: The element's (tag) name.  May cotain a prefix. 
  88          @type name: basestring 
  89          @param parent: An optional parent element. 
  90          @type parent: I{Element} 
  91          @param ns: An optional namespace 
  92          @type ns: (I{prefix}, I{name}) 
  93          """ 
  94           
  95          self.rename(name) 
  96          self.expns = None 
  97          self.nsprefixes = {} 
  98          self.attributes = [] 
  99          self.text = None 
 100          if parent is not None: 
 101              if isinstance(parent, Element): 
 102                  self.parent = parent 
 103              else: 
 104                  raise Exception('parent (%s) not-valid', parent.__class__.__name__) 
 105          else: 
 106              self.parent = None 
 107          self.children = [] 
 108          self.applyns(ns) 
  109           
 111          """ 
 112          Rename the element. 
 113          @param name: A new name for the element. 
 114          @type name: basestring  
 115          """ 
 116          if name is None: 
 117              raise Exception('name (%s) not-valid' % name) 
 118          else: 
 119              self.prefix, self.name = splitPrefix(name) 
  120               
 122          """ 
 123          Set the element namespace prefix. 
 124          @param p: A new prefix for the element. 
 125          @type p: basestring  
 126          @param u: A namespace URI to be mapped to the prefix. 
 127          @type u: basestring 
 128          @return: self 
 129          @rtype: L{Element} 
 130          """ 
 131          self.prefix = p 
 132          if p is not None and u is not None: 
 133              self.addPrefix(p, u) 
 134          return self 
  135   
 137          """ 
 138          Get the B{fully} qualified name of this element 
 139          @return: The fully qualified name. 
 140          @rtype: basestring 
 141          """ 
 142          if self.prefix is None: 
 143              return self.name 
 144          else: 
 145              return '%s:%s' % (self.prefix, self.name) 
  146           
 148          """ 
 149          Get the root (top) node of the tree. 
 150          @return: The I{top} node of this tree. 
 151          @rtype: I{Element} 
 152          """ 
 153          if self.parent is None: 
 154              return self 
 155          else: 
 156              return self.parent.getRoot() 
  157           
 158 -    def clone(self, parent=None): 
  159          """ 
 160          Deep clone of this element and children. 
 161          @param parent: An optional parent for the copied fragment. 
 162          @type parent: I{Element} 
 163          @return: A deep copy parented by I{parent} 
 164          @rtype: I{Element} 
 165          """ 
 166          root = Element(self.qname(), parent, self.namespace()) 
 167          for a in self.attributes: 
 168              root.append(a.clone(self)) 
 169          for c in self.children: 
 170              root.append(c.clone(self)) 
 171          for item in self.nsprefixes.items(): 
 172              root.addPrefix(item[0], item[1]) 
 173          return root 
  174       
 176          """ 
 177          Detach from parent. 
 178          @return: This element removed from its parent's 
 179              child list and I{parent}=I{None} 
 180          @rtype: L{Element} 
 181          """ 
 182          if self.parent is not None: 
 183              if self in self.parent.children: 
 184                  self.parent.children.remove(self) 
 185              self.parent = None 
 186          return self 
  187           
 188 -    def set(self, name, value): 
  189          """ 
 190          Set an attribute's value. 
 191          @param name: The name of the attribute. 
 192          @type name: basestring 
 193          @param value: The attribute value. 
 194          @type value: basestring 
 195          @see: __setitem__() 
 196          """ 
 197          attr = self.getAttribute(name) 
 198          if attr is None: 
 199              attr = Attribute(name, value) 
 200              self.append(attr) 
 201          else: 
 202              attr.setValue(value) 
  203               
 205          """ 
 206          Unset (remove) an attribute. 
 207          @param name: The attribute name. 
 208          @type name: str 
 209          @return: self 
 210          @rtype: L{Element} 
 211          """ 
 212          try: 
 213              attr = self.getAttribute(name) 
 214              self.attributes.remove(attr) 
 215          except: 
 216              pass 
 217          return self 
  218               
 219               
 220 -    def get(self, name, ns=None, default=None): 
  221          """ 
 222          Get the value of an attribute by name. 
 223          @param name: The name of the attribute. 
 224          @type name: basestring 
 225          @param ns: The optional attribute's namespace. 
 226          @type ns: (I{prefix}, I{name}) 
 227          @param default: An optional value to be returned when either 
 228              the attribute does not exist of has not value. 
 229          @type default: basestring 
 230          @return: The attribute's value or I{default} 
 231          @rtype: basestring 
 232          @see: __getitem__() 
 233          """ 
 234          attr = self.getAttribute(name, ns) 
 235          if attr is None or attr.value is None: 
 236              return default 
 237          else: 
 238              return attr.getValue()    
  239   
 240 -    def setText(self, value): 
  241          """ 
 242          Set the element's L{Text} content. 
 243          @param value: The element's text value. 
 244          @type value: basestring 
 245          @return: self 
 246          @rtype: I{Element} 
 247          """ 
 248          if isinstance(value, Text): 
 249              self.text = value 
 250          else: 
 251              self.text = Text(value) 
 252          return self 
  253           
 254 -    def getText(self, default=None): 
  255          """ 
 256          Get the element's L{Text} content with optional default 
 257          @param default: A value to be returned when no text content exists. 
 258          @type default: basestring 
 259          @return: The text content, or I{default} 
 260          @rtype: L{Text} 
 261          """ 
 262          if self.hasText(): 
 263              return self.text 
 264          else: 
 265              return default 
  266       
 268          """ 
 269          Trim leading and trailing whitespace. 
 270          @return: self 
 271          @rtype: L{Element} 
 272          """ 
 273          if self.hasText(): 
 274              self.text = self.text.trim() 
 275          return self 
  276       
 278          """ 
 279          Get whether the element has I{text} and that it is not an empty 
 280          (zero length) string. 
 281          @return: True when has I{text}. 
 282          @rtype: boolean 
 283          """ 
 284          return ( self.text is not None and len(self.text) ) 
  285           
 287          """ 
 288          Get the element's namespace. 
 289          @return: The element's namespace by resolving the prefix, the explicit  
 290              namespace or the inherited namespace. 
 291          @rtype: (I{prefix}, I{name}) 
 292          """ 
 293          if self.prefix is None: 
 294              return self.defaultNamespace() 
 295          else: 
 296              return self.resolvePrefix(self.prefix) 
  297           
 299          """ 
 300          Get the default (unqualified namespace).   
 301          This is the expns of the first node (looking up the tree) 
 302          that has it set. 
 303          @return: The namespace of a node when not qualified. 
 304          @rtype: (I{prefix}, I{name}) 
 305          """ 
 306          p = self 
 307          while p is not None: 
 308              if p.expns is not None: 
 309                  return (None, p.expns) 
 310              else: 
 311                  p = p.parent 
 312          return Namespace.default 
  313               
 315          """ 
 316          Append the specified child based on whether it is an 
 317          element or an attrbuite. 
 318          @param objects: A (single|collection) of attribute(s) or element(s) 
 319              to be added as children. 
 320          @type objects: (L{Element}|L{Attribute}) 
 321          @return: self 
 322          @rtype: L{Element} 
 323          """ 
 324          if not isinstance(objects, (list, tuple)): 
 325              objects = (objects,) 
 326          for child in objects: 
 327              if isinstance(child, Element): 
 328                  self.children.append(child) 
 329                  child.parent = self 
 330                  continue 
 331              if isinstance(child, Attribute): 
 332                  self.attributes.append(child) 
 333                  child.parent = self 
 334                  continue 
 335              raise Exception('append %s not-valid' % child.__class__.__name__) 
 336          return self 
  337       
 338 -    def insert(self, objects, index=0): 
  339          """ 
 340          Insert an L{Element} content at the specified index. 
 341          @param objects: A (single|collection) of attribute(s) or element(s) 
 342              to be added as children. 
 343          @type objects: (L{Element}|L{Attribute}) 
 344          @param index: The position in the list of children to insert. 
 345          @type index: int 
 346          @return: self 
 347          @rtype: L{Element} 
 348          """ 
 349          objects = (objects,) 
 350          for child in objects: 
 351              if isinstance(child, Element): 
 352                  self.children.insert(index, child) 
 353                  child.parent = self 
 354              else: 
 355                  raise Exception('append %s not-valid' % child.__class__.__name__) 
 356          return self 
  357       
 359          """ 
 360          Remove the specified child element or attribute. 
 361          @param child: A child to remove. 
 362          @type child: L{Element}|L{Attribute} 
 363          @return: The detached I{child} when I{child} is an element, else None. 
 364          @rtype: L{Element}|None 
 365          """ 
 366          if isinstance(child, Element): 
 367              return child.detach() 
 368          if isinstance(child, Attribute): 
 369              self.attributes.remove(child) 
 370          return None 
  371               
 373          """ 
 374          Replace I{child} with the specified I{content}. 
 375          @param child: A child element. 
 376          @type child: L{Element} 
 377          @param content: An element or collection of elements. 
 378          @type content: L{Element} or [L{Element},] 
 379          """ 
 380          if child not in self.children: 
 381              raise Exception('child not-found') 
 382          index = self.children.index(child) 
 383          self.remove(child) 
 384          if not isinstance(content, (list, tuple)): 
 385              content = (content,) 
 386          for node in content: 
 387              self.children.insert(index, node.detach()) 
 388              node.parent = self 
 389              index += 1 
  390               
 392          """ 
 393          Get an attribute by name and (optional) namespace 
 394          @param name: The name of a contained attribute (may contain prefix). 
 395          @type name: basestring 
 396          @param ns: An optional namespace 
 397          @type ns: (I{prefix}, I{name}) 
 398          @param default: Returned when attribute not-found. 
 399          @type default: L{Attribute} 
 400          @return: The requested attribute object. 
 401          @rtype: L{Attribute} 
 402          """ 
 403          if ns is None: 
 404              prefix, name = splitPrefix(name) 
 405              if prefix is None: 
 406                  ns = None 
 407              else: 
 408                  ns = self.resolvePrefix(prefix) 
 409          for a in self.attributes: 
 410              if a.match(name, ns): 
 411                  return a 
 412          return default 
  413   
 414 -    def getChild(self, name, ns=None, default=None): 
  415          """ 
 416          Get a child by (optional) name and/or (optional) namespace. 
 417          @param name: The name of a child element (may contain prefix). 
 418          @type name: basestring 
 419          @param ns: An optional namespace used to match the child. 
 420          @type ns: (I{prefix}, I{name}) 
 421          @param default: Returned when child not-found. 
 422          @type default: L{Element} 
 423          @return: The requested child, or I{default} when not-found. 
 424          @rtype: L{Element} 
 425          """ 
 426          if ns is None: 
 427              prefix, name = splitPrefix(name) 
 428              if prefix is None: 
 429                  ns = None 
 430              else: 
 431                  ns = self.resolvePrefix(prefix) 
 432          for c in self.children: 
 433              if c.match(name, ns): 
 434                  return c 
 435          return default 
  436       
 438          """ 
 439          Get a child at I{path} where I{path} is a (/) separated 
 440          list of element names that are expected to be children. 
 441          @param path: A (/) separated list of element names. 
 442          @type path: basestring 
 443          @return: The leaf node at the end of I{path} 
 444          @rtype: L{Element} 
 445          """ 
 446          result = None 
 447          node = self 
 448          for name in [p for p in path.split('/') if len(p) > 0]: 
 449              ns = None 
 450              prefix, name = splitPrefix(name) 
 451              if prefix is not None: 
 452                  ns = node.resolvePrefix(prefix) 
 453              result = node.getChild(name, ns) 
 454              if result is None: 
 455                  break; 
 456              else: 
 457                  node = result 
 458          return result 
  459   
 461          """ 
 462          Get a list of children at I{path} where I{path} is a (/) separated 
 463          list of element names that are expected to be children. 
 464          @param path: A (/) separated list of element names. 
 465          @type path: basestring 
 466          @return: The collection leaf nodes at the end of I{path} 
 467          @rtype: [L{Element},...] 
 468          """ 
 469          parts = [p for p in path.split('/') if len(p) > 0] 
 470          if len(parts) == 1: 
 471              result = self.getChildren(path) 
 472          else: 
 473              result = self.__childrenAtPath(parts) 
 474          return result 
  475           
 477          """ 
 478          Get a list of children by (optional) name and/or (optional) namespace. 
 479          @param name: The name of a child element (may contain prefix). 
 480          @type name: basestring 
 481          @param ns: An optional namespace used to match the child. 
 482          @type ns: (I{prefix}, I{name}) 
 483          @return: The list of matching children. 
 484          @rtype: [L{Element},...] 
 485          """ 
 486          if ns is None: 
 487              if name is None: 
 488                  return self.children 
 489              prefix, name = splitPrefix(name) 
 490              if prefix is None: 
 491                  ns = None 
 492              else: 
 493                  ns = self.resolvePrefix(prefix) 
 494          return [c for c in self.children if c.match(name, ns)] 
  495       
 497          """ 
 498          Detach and return this element's children. 
 499          @return: The element's children (detached). 
 500          @rtype: [L{Element},...] 
 501          """ 
 502          detached = self.children 
 503          self.children = [] 
 504          for child in detached: 
 505              child.parent = None 
 506          return detached 
  507           
 509          """ 
 510          Resolve the specified prefix to a namespace.  The I{nsprefixes} is 
 511          searched.  If not found, it walks up the tree until either resolved or 
 512          the top of the tree is reached.  Searching up the tree provides for 
 513          inherited mappings. 
 514          @param prefix: A namespace prefix to resolve. 
 515          @type prefix: basestring 
 516          @param default: An optional value to be returned when the prefix 
 517              cannot be resolved. 
 518          @type default: (I{prefix},I{URI}) 
 519          @return: The namespace that is mapped to I{prefix} in this context. 
 520          @rtype: (I{prefix},I{URI}) 
 521          """ 
 522          n = self 
 523          while n is not None: 
 524              if prefix in n.nsprefixes: 
 525                  return (prefix, n.nsprefixes[prefix]) 
 526              if prefix in self.specialprefixes: 
 527                  return (prefix, self.specialprefixes[prefix]) 
 528              n = n.parent 
 529          return default 
  530       
 532          """ 
 533          Add or update a prefix mapping. 
 534          @param p: A prefix. 
 535          @type p: basestring 
 536          @param u: A namespace URI. 
 537          @type u: basestring 
 538          @return: self 
 539          @rtype: L{Element} 
 540          """ 
 541          self.nsprefixes[p] = u 
 542          return self 
  543    
 545          """ 
 546          Update (redefine) a prefix mapping for the branch.  
 547          @param p: A prefix. 
 548          @type p: basestring 
 549          @param u: A namespace URI. 
 550          @type u: basestring 
 551          @return: self 
 552          @rtype: L{Element} 
 553          @note: This method traverses down the entire branch! 
 554          """ 
 555          if p in self.nsprefixes: 
 556              self.nsprefixes[p] = u 
 557          for c in self.children: 
 558              c.updatePrefix(p, u) 
 559          return self 
  560               
 562          """ 
 563          Clear the specified prefix from the prefix mappings. 
 564          @param prefix: A prefix to clear. 
 565          @type prefix: basestring 
 566          @return: self 
 567          @rtype: L{Element} 
 568          """ 
 569          if prefix in self.nsprefixes: 
 570              del self.nsprefixes[prefix] 
 571          return self 
  572       
 574          """ 
 575          Find the first prefix that has been mapped to a namespace URI. 
 576          The local mapping is searched, then it walks up the tree until 
 577          it reaches the top or finds a match. 
 578          @param uri: A namespace URI. 
 579          @type uri: basestring 
 580          @param default: A default prefix when not found. 
 581          @type default: basestring 
 582          @return: A mapped prefix. 
 583          @rtype: basestring 
 584          """ 
 585          for item in self.nsprefixes.items(): 
 586              if item[1] == uri: 
 587                  prefix = item[0] 
 588                  return prefix 
 589          for item in self.specialprefixes.items(): 
 590              if item[1] == uri: 
 591                  prefix = item[0] 
 592                  return prefix       
 593          if self.parent is not None: 
 594              return self.parent.findPrefix(uri, default) 
 595          else: 
 596              return default 
  597   
 599          """ 
 600          Find all prefixes that has been mapped to a namespace URI. 
 601          The local mapping is searched, then it walks up the tree until 
 602          it reaches the top collecting all matches. 
 603          @param uri: A namespace URI. 
 604          @type uri: basestring 
 605          @param match: A matching function L{Element.matcher}. 
 606          @type match: basestring 
 607          @return: A list of mapped prefixes. 
 608          @rtype: [basestring,...] 
 609          """ 
 610          result = [] 
 611          for item in self.nsprefixes.items(): 
 612              if self.matcher[match](item[1], uri): 
 613                  prefix = item[0] 
 614                  result.append(prefix) 
 615          for item in self.specialprefixes.items(): 
 616              if self.matcher[match](item[1], uri): 
 617                  prefix = item[0] 
 618                  result.append(prefix) 
 619          if self.parent is not None: 
 620              result += self.parent.findPrefixes(uri, match) 
 621          return result 
  622       
 646       
 648          """ 
 649          Refit namespace qualification by replacing prefixes 
 650          with explicit namespaces. Also purges prefix mapping table. 
 651          @return: self 
 652          @rtype: L{Element} 
 653          """ 
 654          for c in self.children: 
 655              c.refitPrefixes() 
 656          if self.prefix is not None: 
 657              ns = self.resolvePrefix(self.prefix) 
 658              if ns[1] is not None: 
 659                  self.expns = ns[1] 
 660          self.prefix = None 
 661          self.nsprefixes = {} 
 662          return self 
  663                   
 665          """ 
 666          Normalize the namespace prefixes. 
 667          This generates unique prefixes for all namespaces.  Then retrofits all 
 668          prefixes and prefix mappings.  Further, it will retrofix attribute values 
 669          that have values containing (:). 
 670          @return: self 
 671          @rtype: L{Element} 
 672          """ 
 673          PrefixNormalizer.apply(self) 
 674          return self 
  675   
 677          """ 
 678          Get whether the element has no children. 
 679          @param content: Test content (children & text) only. 
 680          @type content: boolean 
 681          @return: True when element has not children. 
 682          @rtype: boolean 
 683          """ 
 684          noattrs = not len(self.attributes) 
 685          nochildren = not len(self.children) 
 686          notext = ( self.text is None ) 
 687          nocontent = ( nochildren and notext ) 
 688          if content: 
 689              return nocontent 
 690          else: 
 691              return ( nocontent and noattrs ) 
  692               
 693               
 695          """ 
 696          Get whether the element is I{nil} as defined by having 
 697          an attribute in the I{xsi:nil="true"} 
 698          @return: True if I{nil}, else False 
 699          @rtype: boolean 
 700          """ 
 701          nilattr = self.getAttribute('nil', ns=Namespace.xsins) 
 702          if nilattr is None: 
 703              return False 
 704          else: 
 705              return ( nilattr.getValue().lower() == 'true' ) 
  706           
 708          """ 
 709          Set this node to I{nil} as defined by having an 
 710          attribute I{xsi:nil}=I{flag}. 
 711          @param flag: A flag inidcating how I{xsi:nil} will be set. 
 712          @type flag: boolean 
 713          @return: self 
 714          @rtype: L{Element} 
 715          """ 
 716          p, u = Namespace.xsins 
 717          name  = ':'.join((p, 'nil')) 
 718          self.set(name, str(flag).lower()) 
 719          self.addPrefix(p, u) 
 720          if flag: 
 721              self.text = None 
 722          return self 
  723               
 725          """ 
 726          Apply the namespace to this node.  If the prefix is I{None} then 
 727          this element's explicit namespace I{expns} is set to the 
 728          URI defined by I{ns}.  Otherwise, the I{ns} is simply mapped. 
 729          @param ns: A namespace. 
 730          @type ns: (I{prefix},I{URI}) 
 731          """ 
 732          if ns is None: 
 733              return 
 734          if not isinstance(ns, (tuple,list)): 
 735              raise Exception('namespace must be tuple') 
 736          if ns[0] is None: 
 737              self.expns = ns[1] 
 738          else: 
 739              self.prefix = ns[0] 
 740              self.nsprefixes[ns[0]] = ns[1] 
  741               
 742 -    def str(self, indent=0): 
  770       
 793   
 795          """ 
 796          Get a string representation for all namespace declarations 
 797          as xmlns="" and xmlns:p="". 
 798          @return: A separated list of declarations. 
 799          @rtype: basestring 
 800          """ 
 801          s = [] 
 802          myns = (None, self.expns) 
 803          if self.parent is None: 
 804              pns = Namespace.default 
 805          else: 
 806              pns = (None, self.parent.expns) 
 807          if myns[1] != pns[1]: 
 808              if self.expns is not None: 
 809                  d = ' xmlns="%s"' % self.expns 
 810                  s.append(d) 
 811          for item in self.nsprefixes.items(): 
 812              (p,u) = item 
 813              if self.parent is not None: 
 814                  ns = self.parent.resolvePrefix(p) 
 815                  if ns[1] == u: continue 
 816              d = ' xmlns:%s="%s"' % (p, u) 
 817              s.append(d) 
 818          return ''.join(s) 
  819       
 820 -    def match(self, name=None, ns=None): 
  821          """ 
 822          Match by (optional) name and/or (optional) namespace. 
 823          @param name: The optional element tag name. 
 824          @type name: str 
 825          @param ns: An optional namespace. 
 826          @type ns: (I{prefix}, I{name}) 
 827          @return: True if matched. 
 828          @rtype: boolean 
 829          """ 
 830          if name is None: 
 831              byname = True 
 832          else: 
 833              byname = ( self.name == name ) 
 834          if ns is None: 
 835              byns = True 
 836          else: 
 837              byns = ( self.namespace()[1] == ns[1] ) 
 838          return ( byname and byns ) 
  839       
 841          """ 
 842          Get a flattened representation of the branch. 
 843          @return: A flat list of nodes. 
 844          @rtype: [L{Element},..] 
 845          """ 
 846          branch = [self] 
 847          for c in self.children: 
 848              branch += c.branch() 
 849          return branch 
  850       
 852          """ 
 853          Get a list of ancestors. 
 854          @return: A list of ancestors. 
 855          @rtype: [L{Element},..] 
 856          """ 
 857          ancestors = [] 
 858          p = self.parent 
 859          while p is not None: 
 860              ancestors.append(p) 
 861              p = p.parent 
 862          return ancestors 
  863       
 864 -    def walk(self, visitor): 
  865          """ 
 866          Walk the branch and call the visitor function 
 867          on each node. 
 868          @param visitor: A function. 
 869          @return: self 
 870          @rtype: L{Element} 
 871          """ 
 872          visitor(self) 
 873          for c in self.children: 
 874              c.walk(visitor) 
 875          return self 
  876       
 878          """ 
 879          Prune the branch of empty nodes. 
 880          """ 
 881          pruned = [] 
 882          for c in self.children: 
 883              c.prune() 
 884              if c.isempty(False): 
 885                  pruned.append(c) 
 886          for p in pruned: 
 887              self.children.remove(p) 
  888                   
 889               
 913       
 916                   
 918          if isinstance(index, basestring): 
 919              return self.get(index) 
 920          else: 
 921              if index < len(self.children): 
 922                  return self.children[index] 
 923              else: 
 924                  return None 
  925           
 927          if isinstance(index, basestring): 
 928              self.set(index, value) 
 929          else: 
 930              if index < len(self.children) and \ 
 931                  isinstance(value, Element): 
 932                  self.children.insert(index, value) 
  933   
 935          return  rhs is not None and \ 
 936              isinstance(rhs, Element) and \ 
 937              self.name == rhs.name and \ 
 938              self.namespace()[1] == rhs.namespace()[1] 
  939           
 941          return \ 
 942              'Element (prefix=%s, name=%s)' % (self.prefix, self.name) 
  943       
 945          return unicode(self).encode('utf-8') 
  946       
 949       
  952       
 955      """ 
 956      The L{Element} child node iterator. 
 957      @ivar pos: The current position 
 958      @type pos: int 
 959      @ivar children: A list of a child nodes. 
 960      @type children: [L{Element},..]  
 961      """ 
 962       
 964          """ 
 965          @param parent: An element to iterate. 
 966          @type parent: L{Element} 
 967          """ 
 968          self.pos = 0 
 969          self.children = parent.children 
  970           
 972          """ 
 973          Get the next child. 
 974          @return: The next child. 
 975          @rtype: L{Element} 
 976          @raise StopIterator: At the end. 
 977          """ 
 978          try: 
 979              child = self.children[self.pos] 
 980              self.pos += 1 
 981              return child 
 982          except: 
 983              raise StopIteration() 
   984   
 987      """ 
 988      The prefix normalizer provides namespace prefix normalization. 
 989      @ivar node: A node to normalize. 
 990      @type node: L{Element} 
 991      @ivar branch: The nodes flattened branch. 
 992      @type branch: [L{Element},..] 
 993      @ivar namespaces: A unique list of namespaces (URI). 
 994      @type namespaces: [str,] 
 995      @ivar prefixes: A reverse dict of prefixes. 
 996      @type prefixes: {u, p} 
 997      """ 
 998       
 999      @classmethod 
1001          """ 
1002          Normalize the specified node. 
1003          @param node: A node to normalize. 
1004          @type node: L{Element} 
1005          @return: The normalized node. 
1006          @rtype: L{Element} 
1007          """ 
1008          pn = PrefixNormalizer(node) 
1009          return pn.refit() 
 1010       
1020           
1022          """ 
1023          Get the I{unique} set of namespaces referenced in the branch. 
1024          @return: A set of namespaces. 
1025          @rtype: set 
1026          """ 
1027          s = set() 
1028          for n in self.branch + self.node.ancestors(): 
1029              if self.permit(n.expns): 
1030                  s.add(n.expns) 
1031              s = s.union(self.pset(n)) 
1032          return s 
 1033       
1034 -    def pset(self, n): 
 1035          """ 
1036          Convert the nodes nsprefixes into a set. 
1037          @param n: A node. 
1038          @type n: L{Element} 
1039          @return: A set of namespaces. 
1040          @rtype: set 
1041          """ 
1042          s = set() 
1043          for ns in n.nsprefixes.items(): 
1044              if self.permit(ns): 
1045                  s.add(ns[1]) 
1046          return s 
 1047               
1049          """ 
1050          Generate a I{reverse} mapping of unique prefixes for all namespaces. 
1051          @return: A referse dict of prefixes. 
1052          @rtype: {u, p} 
1053          """ 
1054          prefixes = {} 
1055          n = 0 
1056          for u in self.namespaces: 
1057              p = 'ns%d' % n 
1058              prefixes[u] = p 
1059              n += 1 
1060          return prefixes 
 1061       
1063          """ 
1064          Refit (normalize) the prefixes in the node. 
1065          """ 
1066          self.refitNodes() 
1067          self.refitMappings() 
 1068       
1070          """ 
1071          Refit (normalize) all of the nodes in the branch. 
1072          """ 
1073          for n in self.branch: 
1074              if n.prefix is not None: 
1075                  ns = n.namespace() 
1076                  if self.permit(ns): 
1077                      n.prefix = self.prefixes[ns[1]] 
1078              self.refitAttrs(n) 
 1079                   
1081          """ 
1082          Refit (normalize) all of the attributes in the node. 
1083          @param n: A node. 
1084          @type n: L{Element} 
1085          """ 
1086          for a in n.attributes: 
1087              self.refitAddr(a) 
 1088       
1090          """ 
1091          Refit (normalize) the attribute. 
1092          @param a: An attribute. 
1093          @type a: L{Attribute} 
1094          """ 
1095          if a.prefix is not None: 
1096              ns = a.namespace() 
1097              if self.permit(ns): 
1098                  a.prefix = self.prefixes[ns[1]] 
1099          self.refitValue(a) 
 1100       
1102          """ 
1103          Refit (normalize) the attribute's value. 
1104          @param a: An attribute. 
1105          @type a: L{Attribute} 
1106          """ 
1107          p,name = splitPrefix(a.getValue()) 
1108          if p is None: return 
1109          ns = a.resolvePrefix(p) 
1110          if self.permit(ns): 
1111              u = ns[1] 
1112              p = self.prefixes[u] 
1113              a.setValue(':'.join((p, name))) 
 1114               
1116          """ 
1117          Refit (normalize) all of the nsprefix mappings. 
1118          """ 
1119          for n in self.branch: 
1120              n.nsprefixes = {} 
1121          n = self.node 
1122          for u, p in self.prefixes.items(): 
1123              n.addPrefix(p, u) 
 1124               
1126          """ 
1127          Get whether the I{ns} is to be normalized. 
1128          @param ns: A namespace. 
1129          @type ns: (p,u) 
1130          @return: True if to be included. 
1131          @rtype: boolean 
1132          """ 
1133          return not self.skip(ns) 
 1134               
1135 -    def skip(self, ns): 
 1136          """ 
1137          Get whether the I{ns} is to B{not} be normalized. 
1138          @param ns: A namespace. 
1139          @type ns: (p,u) 
1140          @return: True if to be skipped. 
1141          @rtype: boolean 
1142          """ 
1143          return ns is None or \ 
1144              ( ns == Namespace.default ) or \ 
1145              ( ns == Namespace.xsdns ) or \ 
1146              ( ns == Namespace.xsins) or \ 
1147              ( ns == Namespace.xmlns ) 
  1148