Commits

Anonymous committed da6bd7b

Modified Files:
LibXML.pm LibXML.xs dom.c dom.h
+ extensive use of ProxyObjects (less segfaults)
+ Document is now a Node
+ Node::setName() (its not aware about namespaces, yet)
+ minor bugfixes

example/libxml.xml
+ documentation updates

t/06nodetypes.t
+ attrbibute tests

Comments (0)

Files changed (6)

 sub XML_XINCLUDE_START(){19;}
 sub XML_XINCLUDE_END(){20;}
 
+@XML::LibXML::Document::ISA         = 'XML::LibXML::Node';
 @XML::LibXML::Element::ISA      = 'XML::LibXML::Node';
 @XML::LibXML::Text::ISA         = 'XML::LibXML::Node';
 @XML::LibXML::Comment::ISA      = 'XML::LibXML::Text';
     OUTPUT:
         RETVAL
 
-xmlDocPtr
+SV*
 _parse_string(self, string)
         SV * self
         SV * string
         char * ptr;
         int well_formed;
         int ret;
+        xmlDocPtr real_dom;
+        ProxyObject * proxy;
     CODE:
         ptr = SvPV(string, len);
         ctxt = xmlCreateMemoryParserCtxt(ptr, len);
         
         well_formed = ctxt->wellFormed;
 
-        if (ctxt->myDoc->encoding == NULL) {
-            ctxt->myDoc->encoding = xmlStrdup("utf-8");
-        }
-
-        RETVAL = ctxt->myDoc;
-        
+        real_dom = ctxt->myDoc;
         xmlFreeParserCtxt(ctxt);
         
         if (!well_formed) {
-            xmlFreeDoc(RETVAL);
+            xmlFreeDoc(real_dom);
+            RETVAL = &PL_sv_undef;    
             croak(SvPV(LibXML_error, len));
         }
+        else {
+            if (real_dom->encoding == NULL) {
+                real_dom->encoding = xmlStrdup("UTF-8");
+            }
+
+            proxy = make_proxy_node( (xmlNodePtr)real_dom ); 
+
+            RETVAL = sv_newmortal();
+            sv_setref_pv( RETVAL, (char *)CLASS, (void*)proxy );
+            proxy->extra = RETVAL;
+            SvREFCNT_inc(RETVAL);
+        }
     OUTPUT:
         RETVAL
 
-xmlDocPtr
+SV*
 _parse_fh(self, fh)
         SV * self
         SV * fh
     PREINIT:
         char * CLASS = "XML::LibXML::Document";
         STRLEN len;
+        xmlDocPtr real_dom;
+        ProxyObject* proxy;
     CODE:
-        RETVAL = LibXML_parse_stream(self, fh);
-        if (RETVAL == NULL) {
+        real_dom = LibXML_parse_stream(self, fh);
+        if (real_dom == NULL) {
+            RETVAL = &PL_sv_undef;    
             croak(SvPV(LibXML_error, len));
         }
+        else {
+            if (real_dom->encoding == NULL) {
+                real_dom->encoding = xmlStrdup("UTF-8");
+            }
+       
+            proxy = make_proxy_node( (xmlNodePtr)real_dom ); 
+
+            RETVAL = sv_newmortal();
+            sv_setref_pv( RETVAL, (char *)CLASS, (void*)proxy );
+            proxy->extra = RETVAL;
+            SvREFCNT_inc(RETVAL);
+        }
     OUTPUT:
         RETVAL
         
-xmlDocPtr
+SV*
 _parse_file(self, filename)
         SV * self
         const char * filename
     PREINIT:
         xmlParserCtxtPtr ctxt;
         char * CLASS = "XML::LibXML::Document";
-        int ret;
+        int well_formed;
         STRLEN len;
+        xmlDocPtr real_dom;
+        ProxyObject * proxy;
     CODE:
         ctxt = xmlCreateFileParserCtxt(filename);
         if (ctxt == NULL) {
         ctxt->_private = (void*)self;
         
         xmlParseDocument(ctxt);
-        RETVAL = ctxt->myDoc;
-        if (RETVAL->encoding == NULL) {
-            RETVAL->encoding = xmlStrdup("utf-8");
-        }
-        ret = ctxt->wellFormed;
-        
+        well_formed = ctxt->wellFormed;
+
+        real_dom = ctxt->myDoc;
         xmlFreeParserCtxt(ctxt);
         
-        if (!ret) {
-            xmlFreeDoc(RETVAL);
+        if (!well_formed) {
+            xmlFreeDoc(real_dom);
+            RETVAL = &PL_sv_undef ;  
             croak(SvPV(LibXML_error, len));
         }
+        else {
+            if (real_dom->encoding == NULL) {
+                real_dom->encoding = xmlStrdup("UTF-8");
+            }
+
+            proxy = make_proxy_node( (xmlNodePtr)real_dom ); 
+
+            RETVAL = sv_newmortal();
+            sv_setref_pv( RETVAL, (char *)CLASS, (void*)proxy );
+            proxy->extra = RETVAL;
+            SvREFCNT_inc(RETVAL);
+        }
     OUTPUT:
         RETVAL
 
 
 void
 DESTROY(self)
-        xmlDocPtr self
+        ProxyObject* self
     CODE:
-        if (self == NULL) {
-           XSRETURN_UNDEF;
-        }
-             
-        # warn("xmlFreeDoc(%d)\n", self);
-        xmlFreeDoc(self);
 
 
 SV *
 toString(self, format=0)
-        xmlDocPtr self
+        ProxyObject* self
         int format
     PREINIT:
+        xmlDocPtr real_dom;
         xmlChar *result;
         int len;
     CODE:
+        real_dom = (xmlDocPtr)self->object;
         if ( format <= 0 ) {
-            xmlDocDumpMemory(self, &result, &len);
+            xmlDocDumpMemory(real_dom, &result, &len);
         }
         else {
             int t_indent_var = xmlIndentTreeOutput;
             xmlIndentTreeOutput = 1;
-            xmlDocDumpFormatMemory( self, &result, &len, format ); 
+            xmlDocDumpFormatMemory( real_dom, &result, &len, format ); 
             xmlIndentTreeOutput = t_indent_var;
         }
     	if (result == NULL) {
             RETVAL = newSVpvn((char *)result, (STRLEN)len);
 	        xmlFree(result);
 	    }
-        xmlReconciliateNs(self,xmlDocGetRootElement(self));
+        xmlReconciliateNs(real_dom,xmlDocGetRootElement(real_dom));
     OUTPUT:
         RETVAL
 
 int
 is_valid(self, ...)
-        xmlDocPtr self
+        ProxyObject* self
     PREINIT:
+        xmlDocPtr real_dom;
         xmlValidCtxt cvp;
         xmlDtdPtr dtd;
         SV * dtd_sv;
     CODE:
+        real_dom = (xmlDocPtr)self->object;
         if (items > 1) {
             dtd_sv = ST(1);
             if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
             cvp.userData = (void*)PerlIO_stderr();
             cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
             cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
-            RETVAL = xmlValidateDtd(&cvp, self, dtd);
+            RETVAL = xmlValidateDtd(&cvp, real_dom , dtd);
         }
         else {
-            RETVAL = xmlValidateDocument(&cvp, self);
+            RETVAL = xmlValidateDocument(&cvp, real_dom);
         }
     OUTPUT:
         RETVAL
 
 void
 process_xinclude(self)
-        xmlDocPtr self
+        ProxyObject* self
     CODE:
-        xmlXIncludeProcess(self);
+        xmlXIncludeProcess((xmlDocPtr)self->object);
 
-xmlDocPtr
-new( CLASS, version="1.0", encoding=0 )
-        char * CLASS
-        char * version 
-        char * encoding
-    CODE:
-        RETVAL = domCreateDocument( version, encoding ); 
-    OUTPUT:
-        RETVAL
-
-xmlDocPtr
+SV*
 createDocument( CLASS, version="1.0", encoding=0 )
         char * CLASS
         char * version 
         char * encoding
+    ALIAS:
+        XML::LibXML::Document::new = 1
+    PREINIT:
+        xmlDocPtr real_dom=NULL;
+        ProxyObject * ret= NULL;
     CODE:
-        RETVAL = domCreateDocument( version, encoding ); 
+        real_dom = domCreateDocument( version, encoding ); 
+        ret = make_proxy_node( (xmlNodePtr)real_dom );
+        RETVAL = sv_newmortal();
+        sv_setref_pv( RETVAL, (char *)CLASS, (void*)ret );
+        ret->extra = RETVAL;
+        SvREFCNT_inc(RETVAL);
     OUTPUT:
         RETVAL
 
         xmlNodePtr newNode;
     CODE:
         newNode = xmlNewNode( 0 , name );
-        newNode->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        newNode->doc =(xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         RETVAL = make_proxy_node(newNode);
         RETVAL->extra = dom;
         SvREFCNT_inc(dom);
          lname = xmlSplitQName2(qname, &prefix);
          ns = domNewNs (0 , prefix , nsURI);
          newNode = xmlNewNode( ns , lname );
-         newNode->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+         newNode->doc =(xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
          RETVAL = make_proxy_node(newNode);
          RETVAL->extra = dom;
          SvREFCNT_inc(dom);
         char * CLASS = "XML::LibXML::Text";
         xmlNodePtr newNode;
     CODE:
-        newNode = xmlNewDocText( (xmlDocPtr)SvIV((SV*)SvRV(dom)), content );
+        newNode = xmlNewDocText( (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object, content );
         RETVAL = make_proxy_node(newNode);
         RETVAL->extra = dom;
         SvREFCNT_inc(dom);
         char * CLASS = "XML::LibXML::Comment";
         xmlNodePtr newNode;
     CODE:
-        newNode = xmlNewDocComment( (xmlDocPtr)SvIV((SV*)SvRV(dom)), content );
+        newNode = xmlNewDocComment( (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object, content );
         RETVAL = make_proxy_node(newNode);
         RETVAL->extra = dom;
         SvREFCNT_inc(dom);
         char * CLASS = "XML::LibXML::CDATASection";
         xmlNodePtr newNode;
     CODE:
-        newNode = domCreateCDATASection( (xmlDocPtr)SvIV((SV*)SvRV(dom)), content );
+        newNode = domCreateCDATASection( (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object, content );
         RETVAL = make_proxy_node(newNode);
         RETVAL->extra = dom;
         SvREFCNT_inc(dom);
         xmlNodePtr newNode;
     CODE:
         newNode = (xmlNodePtr)xmlNewProp(NULL, name , value );
-        newNode->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        newNode->doc = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         if ( newNode->children!=NULL ) {
-            newNode->children->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+            newNode->children->doc = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         }
         RETVAL = make_proxy_node(newNode);
         RETVAL->extra = dom;
         }
         ns = domNewNs (0 , prefix , nsURI);
         newNode = (xmlNodePtr)xmlNewNsProp(NULL, ns, lname , value );
-        newNode->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        newNode->doc = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         if ( newNode->children!=NULL ) {
-            newNode->children->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+            newNode->children->doc = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         }
         RETVAL = make_proxy_node(newNode);
         RETVAL->extra = dom;
         xmlDocPtr real_dom;
         xmlNodePtr elem;
     CODE:
-        real_dom = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         SvREFCNT_dec(proxy->extra);
         elem = (xmlNodePtr)proxy->object;
         domSetDocumentElement( real_dom, elem );
         xmlNodePtr elem;
         xmlDocPtr real_dom;
     CODE:
-        real_dom = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         RETVAL = NULL;
         elem = domDocumentElement( real_dom ) ;
         if ( elem ) {
         xmlNodePtr ret;
         xmlDocPtr real_dom;
     CODE:
-        real_dom = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
         RETVAL = NULL;
         ret = domImportNode( real_dom, node, move );
         if ( ret ) {
 
 char*
 getEncoding( self )
-         xmlDocPtr self
+         ProxyObject* self
     CODE:
-        if( self != NULL ) {
-            RETVAL = xmlStrdup( self->encoding );
+        if( self != NULL && self->object!=NULL) {
+            RETVAL = xmlStrdup( ((xmlDocPtr)self->object)->encoding );
         }
     OUTPUT:
         RETVAL
 
 char*
 getVersion( self ) 
-         xmlDocPtr self
+         ProxyObject* self
     CODE:
-        if( self != NULL ) {
-            RETVAL = xmlStrdup( self->version );
-        }
-    OUTPUT:
-        RETVAL
-
-int 
-isEqual( self, other )
-        xmlDocPtr self
-        xmlDocPtr other
-    CODE:
-        RETVAL = 0;
-        if( self == other ) {
-            RETVAL = 1;
+        if( self != NULL && self->object != NULL) {
+            RETVAL = xmlStrdup( ((xmlDocPtr)self->object)->version );
         }
     OUTPUT:
         RETVAL
 void
 DESTROY( node )
         ProxyObject * node
+    PREINIT:
+        xmlNodePtr real_node;
     CODE:
-        /**
-         * this block should remove old (unbound) nodes from the system
-         * but for some reason this condition is not valid ... :(
-         **/
-        if (node->extra != NULL) {
-            SvREFCNT_dec(node->extra);
+        if (node == NULL) {
+           XSRETURN_UNDEF;
         }
 
-        # warn( "Free node\n" );
-        Safefree(node); 
-    
-    
+        real_node = node->object;
+        if ( real_node != NULL ) {
+            if( real_node->type == XML_DOCUMENT_NODE ){
+                Safefree(node); 
+                # warn("xmlFreeDoc(%d)\n", real_node);
+                xmlFreeDoc((xmlDocPtr)real_node);
+                node->object = NULL;
+                node->extra  = &PL_sv_undef;
+            }
+            else {
+                /**
+                 * this block should remove old (unbound) nodes from the system
+                 * but for some reason this condition is not valid ... :(
+                 **/
+                if (node->extra != NULL) {
+                    SvREFCNT_dec(node->extra);
+                }
+                Safefree(node); 
+            }
+            # warn( "Free node\n" );
+        }
 	
 int 
 getType( node ) 
 
 ProxyObject *
 replaceChild( paren, newChild, oldChild ) 
-        xmlNodePtr paren
-        xmlNodePtr newChild
+        ProxyObject* paren
+        ProxyObject* newChild
         xmlNodePtr oldChild
     PREINIT:
+        ProxyObject* pproxy = NULL;
+        ProxyObject* cproxy = NULL;
         const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = domReplaceChild( paren, newChild, oldChild );
+        ret = domReplaceChild( paren->object, newChild->object, oldChild );
         RETVAL = NULL;
         if (ret != NULL) {
             CLASS = domNodeTypeName( ret );
             RETVAL = make_proxy_node(ret);
+            
+            if ( paren->extra != NULL ){
+                pproxy = (ProxyObject*)SvIV((SV*)SvRV(paren->extra));
+            }
+            if (  newChild->extra != NULL ) {
+                cproxy = (ProxyObject*)SvIV((SV*)SvRV(newChild->extra));
+            }
+            if ( pproxy == NULL || 
+                 cproxy == NULL || 
+                 pproxy->object != cproxy->object ) {
+      
+                # warn("different documents");
+                if ( newChild->extra != NULL ){
+                    # warn("decrease child documents");   
+                    SvREFCNT_dec(newChild->extra);
+                }
+
+                newChild->extra = paren->extra;
+                RETVAL->extra   = paren->extra;
+
+                if ( newChild->extra != NULL ){
+                    # warn("increase child documents");   
+                    SvREFCNT_inc(newChild->extra);
+                    SvREFCNT_inc(newChild->extra);
+                }
+            }
         }
     OUTPUT:
         RETVAL
 
 void
 appendChild( parent, child )
-        xmlNodePtr parent
-        xmlNodePtr child
+        ProxyObject* parent
+        ProxyObject* child
+    PREINIT:
+        ProxyObject* pproxy = NULL;
+        ProxyObject* cproxy = NULL;
     CODE:
-        domAppendChild( parent, child );
+        domAppendChild( parent->object, child->object );
+        # update the proxies if nessecary
+        
+        if ( parent->extra != NULL ){
+            pproxy = (ProxyObject*)SvIV((SV*)SvRV(parent->extra));
+        }
+        if ( child->extra != NULL ) {
+            cproxy = (ProxyObject*)SvIV((SV*)SvRV(child->extra));
+        }
+        if ( pproxy == NULL || 
+             cproxy == NULL || 
+             pproxy->object != cproxy->object ) {
+      
+            # warn("different documents");
+            if ( child->extra != NULL ){
+                # warn("decrease child documents");   
+                SvREFCNT_dec(child->extra);
+            }
+
+            child->extra = parent->extra;
+
+            if ( child->extra != NULL ){
+                # warn("increase child documents");   
+                SvREFCNT_inc(child->extra);
+            }
+        }
 
 ProxyObject *
 cloneNode( self, deep ) 
-        xmlNodePtr self
+        ProxyObject* self
         int deep
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = xmlCopyNode( self, deep );
+        ret = xmlCopyNode( (xmlNodePtr)self->object, deep );
         RETVAL = NULL;
         if (ret != NULL) {
             CLASS = domNodeTypeName( ret );
             RETVAL = make_proxy_node(ret);
+            if( self->extra != NULL ) {
+                RETVAL->extra = self->extra ;
+                SvREFCNT_inc(self->extra);                
+            }
         }
     OUTPUT:
         RETVAL
 
 ProxyObject *
 getParentNode( self )
-        xmlNodePtr self
+        ProxyObject* self
     PREINIT:
         const char * CLASS = "XML::LibXML::Element";
         xmlNodePtr ret;
     CODE:
-        ret = self->parent;
+        ret = ((xmlNodePtr)self->object)->parent;
         RETVAL = NULL;
         if (ret != NULL) {
             RETVAL = make_proxy_node(ret);
+            if( self->extra != NULL ) {
+                RETVAL->extra = self->extra ;
+                SvREFCNT_inc(self->extra);                
+            }
         }
     OUTPUT:
         RETVAL
 
 ProxyObject *
 getNextSibling( elem )
-        xmlNodePtr elem
+        ProxyObject* elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = elem->next ;
+        ret = ((xmlNodePtr)elem->object)->next ;
         RETVAL = NULL;
         if ( ret ) {
             CLASS = domNodeTypeName( ret );
             RETVAL = make_proxy_node(ret);
+            if( elem->extra != NULL ) {
+                RETVAL->extra = elem->extra ;
+                SvREFCNT_inc(elem->extra);                
+            }
         }	
     OUTPUT:
         RETVAL
 
 ProxyObject *
 getPreviousSibling( elem )
-        xmlNodePtr elem
+        ProxyObject* elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = elem->prev;
+        ret = ((xmlNodePtr)elem->object)->prev;
         RETVAL = NULL;
         if ( ret ) {
             CLASS = domNodeTypeName( ret );
             RETVAL = make_proxy_node(ret);
+            if( elem->extra != NULL ) {
+                RETVAL->extra = elem->extra ;
+                SvREFCNT_inc(elem->extra);                
+            }
         }
     OUTPUT:
         RETVAL
 
 ProxyObject *
 getFirstChild( elem )
-        xmlNodePtr elem
+        ProxyObject* elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = elem->children;
+        ret = ((xmlNodePtr)elem->object)->children;
         RETVAL = NULL;
         if ( ret ) {
             CLASS = domNodeTypeName( ret );
             RETVAL = make_proxy_node(ret);
+            if( elem->extra != NULL ) {
+                RETVAL->extra = elem->extra ;
+                SvREFCNT_inc(elem->extra);                
+            }
         }
     OUTPUT:
         RETVAL
 
 ProxyObject *
 getLastChild( elem )
-        xmlNodePtr elem
+        ProxyObject* elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = elem->last;
+        ret = ((xmlNodePtr)elem->object)->last;
         RETVAL = NULL;
         if ( ret ) {
             CLASS = domNodeTypeName( ret );
             RETVAL = make_proxy_node(ret);
+            if( elem->extra != NULL ) {
+                RETVAL->extra = elem->extra ;
+                SvREFCNT_inc(elem->extra);
+            }
         }
     OUTPUT:
         RETVAL
 
 void
 insertBefore( self, new, ref ) 
-        xmlNodePtr self
-        xmlNodePtr new
+        ProxyObject* self
+        ProxyObject* new
         xmlNodePtr ref
+    PREINIT:
+        ProxyObject* pproxy= NULL;
+        ProxyObject* cproxy= NULL; 
     CODE:
-        domInsertBefore( self, new, ref );
+        domInsertBefore( self->object, new->object, ref );
+        if ( self->extra != NULL ){
+            pproxy = (ProxyObject*)SvIV((SV*)SvRV(self->extra));
+        }
+        if ( new->extra != NULL ) {
+            cproxy = (ProxyObject*)SvIV((SV*)SvRV(new->extra));
+        }
+        if ( pproxy == NULL || 
+             cproxy == NULL || 
+             pproxy->object != cproxy->object ) {
+      
+            # warn("different documents");
+            if ( new->extra != NULL ){
+                # warn("decrease child documents");   
+                SvREFCNT_dec(new->extra);
+            }
+
+            new->extra = self->extra;
+
+            if ( new->extra != NULL ){
+                # warn("increase child documents");   
+                SvREFCNT_inc(new->extra);
+            }
+        }
+
 
 void
 insertAfter( self, new, ref )
-        xmlNodePtr self
-        xmlNodePtr new
+        ProxyObject* self
+        ProxyObject* new
         xmlNodePtr ref
+    PREINIT:
+        ProxyObject* pproxy= NULL;
+        ProxyObject* cproxy= NULL; 
     CODE:
-        domInsertAfter( self, new, ref );
+        domInsertAfter( self->object, new->object, ref );
+        if ( self->extra != NULL ){
+            pproxy = (ProxyObject*)SvIV((SV*)SvRV(self->extra));
+        }
+        if ( new->extra != NULL ) {
+            cproxy = (ProxyObject*)SvIV((SV*)SvRV(new->extra));
+        }
+        if ( pproxy == NULL || 
+             cproxy == NULL || 
+             pproxy->object != cproxy->object ) {
+      
+            # warn("different documents");
+            if ( new->extra != NULL ){
+                # warn("decrease child documents");   
+                SvREFCNT_dec(new->extra);
+            }
 
-xmlDocPtr
+            new->extra = self->extra;
+
+            if ( new->extra != NULL ){
+                # warn("increase child documents");   
+                SvREFCNT_inc(new->extra);
+            }
+        }
+
+
+SV*
 getOwnerDocument( elem )
-        xmlNodePtr elem
-    PREINIT:
-        const char * CLASS = "XML::LibXML::NoGCDocument";
+        ProxyObject* elem
     CODE:
-        RETVAL = elem->doc;
+        RETVAL = elem->extra;
     OUTPUT:
         RETVAL
 
 void
 setOwnerDocument( elem, doc )
-        xmlNodePtr elem
-        xmlDocPtr doc
+        ProxyObject* elem
+        ProxyObject* doc
+    PREINIT:
+        xmlDocPtr real_doc;
     CODE:
-        domSetOwnerDocument( elem, doc );
+        real_doc = (xmlDocPtr)doc->object;
+        domSetOwnerDocument( elem->object, real_doc );
 
 SV*
 getName( node )
         else {
             RETVAL = &PL_sv_undef;
         }
-
     OUTPUT:
         RETVAL
 
+void
+setName( node , value )
+        xmlNodePtr node
+        char * value
+    CODE:
+        domSetName( node, value );
+
 SV*
 getData( node ) 
         xmlNodePtr node 
 
 SV*
 findnodes( node, xpath )
-        xmlNodePtr node
+        ProxyObject* node
         char * xpath 
     PREINIT:
         xmlNodeSetPtr nodelist;
         int len;
     PPCODE:
         len = 0;
-        nodelist = domXPathSelect( node, xpath );
+        nodelist = domXPathSelect( node->object, xpath );
         if ( nodelist && nodelist->nodeNr > 0 ) {
             int i = 0 ;
             const char * cls = "XML::LibXML::Node";
                 element = sv_newmortal();
                 
                 proxy = make_proxy_node(tnode);
+                if ( node->extra != NULL ) {
+                    proxy->extra = node->extra;
+                    SvREFCNT_inc(node->extra);
+                }
 
                 cls = domNodeTypeName( tnode );
                 XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
 
 SV*
 getChildnodes( node )
-        xmlNodePtr node
+        ProxyObject* node
     PREINIT:
         xmlNodePtr cld;
         SV * element;
     PPCODE:
         len = 0;
 	
-        cld = node->children;
+        cld = ((xmlNodePtr)node->object)->children;
         while ( cld ) {	
             element = sv_newmortal();
             cls = domNodeTypeName( cld );
             proxy = make_proxy_node(cld);
+            if ( node->extra != NULL ) {
+                proxy->extra = node->extra;
+                SvREFCNT_inc(node->extra);
+            }
             XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
             cld = cld->next;
             len++;
     OUTPUT:
         RETVAL
 
-
 void
 setAttribute( elem, name, value )
         xmlNodePtr elem	
         ns = domNewNs (elem , prefix , nsURI);
         xmlSetNsProp( elem, ns, lname, value );
 
+# this is a dummy!
 ProxyObject *
 setAttributeNode( elem, attrnode ) 
-        xmlNodePtr elem
-        xmlNodePtr attrnode 
+        ProxyObject* elem
+        ProxyObject* attrnode 
     PREINIT:
         const char * CLASS = "XML::LibXML::Attr";
     CODE:
+        RETVAL = NULL;        
     OUTPUT:
         RETVAL
 
 
 SV*
 getAttribute( elem, name ) 
-        xmlNodePtr elem
+        ProxyObject* elem
         char * name 
     PREINIT:
 	    char * content;
     CODE:
-        content = xmlGetProp( elem, name );
+        content = xmlGetProp( elem->object, name );
         if ( content != NULL ) {
             RETVAL  = newSVpvn( content, xmlStrlen( content ) );
         }
 
 SV*
 getAttributeNS( elem, nsURI ,name ) 
-        xmlNodePtr elem
+        ProxyObject* elem
         char * nsURI
         char * name 
     PREINIT:
         xmlAttrPtr att;
 	    char * content;
     CODE:
-        att = domHasNsProp( elem, name, nsURI );
+        att = domHasNsProp( elem->object, name, nsURI );
         if ( att != NULL && att->children != NULL ) {
             content = att->children->content;
         }
         attrnode = xmlHasProp( elem, name );
         if ( attrnode != NULL ) {
             RETVAL = make_proxy_node((xmlNodePtr)attrnode);
-            RETVAL->extra = elemobj->extra;
-            SvREFCNT_inc(elemobj->extra);
+            if ( elemobj->extra != NULL ){
+                RETVAL->extra = elemobj->extra;
+                SvREFCNT_inc(elemobj->extra);
+            }
         }
         else {
             RETVAL = NULL;
         attrnode = domHasNsProp( elem, name, nsURI );
         if ( attrnode != NULL ) {
             RETVAL = make_proxy_node((xmlNodePtr)attrnode);
-            RETVAL->extra = elemobj->extra;
-            SvREFCNT_inc(elemobj->extra);
+            if ( elemobj->extra != NULL ) {
+                RETVAL->extra = elemobj->extra;
+                SvREFCNT_inc(elemobj->extra);
+            }
         }
         else {
             RETVAL = NULL;
 
 SV*
 getElementsByTagName( elem, name )
-        xmlNodePtr elem
+        ProxyObject* elem
         char * name 
     PREINIT:
         xmlNodeSetPtr nodelist;
         int len;
     PPCODE:
         len = 0;
-        nodelist = domGetElementsByTagName( elem , name );
+        nodelist = domGetElementsByTagName( elem->object , name );
         if ( nodelist && nodelist->nodeNr > 0 ) {
             int i = 0 ;
             const char * cls = "XML::LibXML::Node";
                 element = sv_newmortal();
                 
                 proxy = make_proxy_node(tnode);
-
+                if ( elem->extra != NULL ) {
+                    proxy->extra = elem->extra;
+                    SvREFCNT_inc(elem->extra);
+                }
                 cls = domNodeTypeName( tnode );
                 XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
             }
 
 SV*
 getElementsByTagNameNS( node, nsURI, name )
-        xmlNodePtr node
+        ProxyObject* node
         char * nsURI
         char * name 
     PREINIT:
         int len;
     PPCODE:
         len = 0;
-        nodelist = domGetElementsByTagNameNS( node , nsURI , name );
+        nodelist = domGetElementsByTagNameNS( node->object , nsURI , name );
         if ( nodelist && nodelist->nodeNr > 0 ) {
             int i = 0 ;
             const char * cls = "XML::LibXML::Node";
                 element = sv_newmortal();
                 
                 proxy = make_proxy_node(tnode);
+                if ( node->extra != NULL ) {
+                    proxy->extra = node->extra;
+                    SvREFCNT_inc(node->extra);
+                }
 
                 cls = domNodeTypeName( tnode );
                 XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
   return qname;
 }
 
+void
+domSetName( xmlNodePtr node, xmlChar* name ) {
+  /* TODO: add ns support */
+  if ( node == NULL || name == NULL ) 
+    return ;
+  if ( node->name != NULL ) {
+    /* required since node->name is const! */
+    xmlFree( (void*) node->name );
+  }
+  node->name = xmlStrdup( name );
+}
 
 xmlNodePtr
 domAppendChild( xmlNodePtr self,
 /* A.1 DOM specified section */
 
 const xmlChar *
-domName( xmlNodePtr );
+domName( xmlNodePtr node );
+
+void
+domSetName( xmlNodePtr node, xmlChar* name );
 
 xmlNodePtr
 domAppendChild( xmlNodePtr self,

example/libxml.xml

 	scratch. The DOM Document Class provides functions that are
 	conform to the DOM Core naming style.
 
+    It inherits all functions from <i>XML::LibXML::Node</i> as
+    specified in DOM Level2. This enables to access the nodes beside
+    the root element on document level - a <i>DTD</i> for example. The
+    support for these nodes is limited at the moment, so I would
+    recommend, not to use <i>node</i> functions on <i>documents<i>.
+
     It is suggested that one should always create a node not bound to
     any document.  There is no need of really including the node to
     the document, but once the node is bound to a document, it is
 
      Both parameter are optional. The default value for <b>$version</b> is
      <i>1.0</i>, of course. If the <b>$encoding</b> parameter is not set,
-     the encoding will be left unset, which means UTF8 is implied.
+     the encoding will be left unset, which means UTF8 is implied (and set).
 
-     The parameter less call of <b>createDocument</b> wil result the 
+     The call of <b>createDocument</b> without any parameter will result the
      following code:
 
 <example><![CDATA[
     returns the version string of the document
 </method>
 
-<method name="isEqual" synopsis="$bool = $doc->isEqual( $other_doc );">
-    returns TRUE (1) if documents refer to the same documentstructure,
-    otherwise FALSE (0) is returned.
-</method>
-
 <method name="toString" 
 	synopsis="$docstring = $dom->toString([$format]);">
 	<b>toString</b> is a deparsing function, so the DOM Tree can
 </method>
 
 <method name="createAttribute"
-     synopsis="$doc->createAttribute($name [,$value]);">
-     Creates a new Attribute node.  
+     synopsis="$attrnode = $doc->createAttribute($name [,$value]);">
+     Creates a new Attribute node. This function is rather useless at
+     the moment, since there is no setAttributeNode function defined
+     in <i>XML::LibXML::Element</i>, yet. 
+</method>
+<method name="createAttributeNS"
+     synopsis="$attrnode = $doc->createAttributeNS( namespaceURI, $name [,$value] );">
+     Creates an Attribute bound to a namespace.
 </method>
 
 <method name="createCDATASection" synopsis="$cdata = $dom->create( $cdata_content );">
 
 <method name="getName" 
 	synopsis="$name = $node->getName();">
-	Returns the node's name
+	Returns the node's name. This Function is aware about namesaces
+	and returns the full name of the current node
+	(<i>prefix:localname</i>)
+</method>
+
+<method name="setName"
+    synopsis="$node->setName( $newName );"> 
+    In very limited situation it is usefull to change a nodes name. In
+    the DOM specification this should throw an error. This Function is 
+    not aware about namespaces yet. 
 </method>
 
 <method name="isEqual" synopsis="$bool = $node->isEqual( $other_node );">
 <method name="getType" 
 	synopsis="$type = $node->getType();">
 	Retrun the node's type. The possible types are described in
-	the libxml2 <b>tree.h</b> documentation.
+	the libxml2 <b>tree.h</b> documentation. The return value of this 
+    function is a numeric value. Therefore it differst with the result
+    of perl ref function.
 </method>
 
 <method name="unbindNode" 
 	sibling if any.
 </method>
 
+<method name="hasChildNodes"
+    synopsis="$boolean = $node->hasChildNodes();"> 
+    If the current node has Childnodes this function returns TRUE (1),
+    otherwise it returns FALSE (0, not undef).
+</method>
+
 <method name="getFirstChild" synopsis="$childnode = $node->getFirstChild()">
 	If a node has childnodes this function will return the first
 	node in the childlist. 
   <item name="XML::LibXML::Comment"/>
   <item name="XML::LibXML::Attr"/>
 </also>
-<version>0.90_a</version>
+<version>0.93</version>
 </class>
 
 <class name="XML::LibXML::Element">
 	Namespaceversion of <i>getAttribute</i>.
 </method>
 
+<method name="getAttributeNode"
+    synopsis="$attrnode = $node->getAttributeNode( $aname );">
+
+    Returns the attribute as a node if the attribute exists. If the
+    Attribute does not exists <i>undef</i> will be returned. 
+</method>
+
+<method name="getAttributeNodeNS"
+    synopsis="$attrnode = $node->getAttributeNodeNS( $namespaceURI, $aname );">
+    Namespaceversion of <i>getAttributeNode</i>. 
+</method>
+
 <method name="removeAttribute" synopsis="$node->removeAttribute( $aname );">
 	The method removes the attribute <i>$aname</i> from the node's
 	attribute list, if the attribute can be found.
 	$elem2->appendChild( $elem3 );
 	ok( not defined $elem3->getOwnerDocument() );
   }
-
  }
 
 }