Clone attributes as needed. Added Node.xpath, Node.match.
[tx] / nodes.py
index fabbee6..c66dac0 100644 (file)
--- a/nodes.py
+++ b/nodes.py
@@ -70,6 +70,18 @@ def _combineAdjacentText( nodes ) :
                        lastTextNode = None
        return tuple( result )
 
+def _processAttributes( attributes ) :
+
+       '''Clone attributes that are already part of another tree (which have
+       a parent).'''
+
+       result = []
+       for attribute in attributes :
+               if attribute.parent is not None :
+                       attribute = attribute.clone()
+               result.append( attribute )
+       return tuple( result )
+
 def _chainNodes( nodes , parent ) :
 
        '''Update parent, prev and next reference for nodes in 'nodes'.  The
@@ -268,14 +280,18 @@ class Node( object ) :
                        raise NodeError( 'prev reference is already set' )
                self.prev = node
 
+       def xpath( self , path ) :
+
+               import xpath
+               xpathObject = xpath.XPath( path )
+               return xpathObject.eval( self )
+
        def __getitem__( self , path ) :
 
                if not isinstance( path , basestring ) :
                        return super( Node , self ).__getitem__( path )
                else :
-                       import xpath
-                       xpathObject = xpath.XPath( path )
-                       return xpathObject.eval( self )
+                       return self.xpath( path )
 
        # Abusing operator overloading
        def __div__( self , path ) :
@@ -286,6 +302,11 @@ class Node( object ) :
 
                raise NotImplementedError
 
+       def match( self , pat ) :
+
+               import pattern
+               return pattern.test( self , pat )
+
        def __cmp__( self , other ) :
 
                if other is self :
@@ -528,7 +549,7 @@ class Element( Node ) :
 
                self.name = name
                self.children = children
-               self.attributes = tuple( attributes )
+               self.attributes = _processAttributes( attributes )
 
                _chainNodes( self.children , self )
                _chainNodes( self.attributes , self )