Commits

Anonymous committed 8513b0f

ok, this is a mid release commit. i cleaned the code a lot. as a result
the entire module should be more stable now and more easy to maintain.
this version does not implement the memory management code, i still have in
my mind.

because everytime a node is retured a new scalar is created, this version
leaks as hell (probably all earlier versions did as well). this will
change with one of the next commits.

one other thing left to do, is to make a switch for toString available, so
a user may decide wether to recieve the string as UTF8 or as the DOM
encoding.

Modified Files:
LibXML.xs
+ over all cleanup
+ recognize strings as utf8 or document encoding (only perl 5.6.x+)
+ all string returned are utf8 (perl flag is set correctly)
++ removed a lot redundand code (almost all SvREFCNT*() calls)
- $ORIGINAL_STRING code (was a bad idea, sorry for adding it)

MANIFEST
+ perl-libxml-mm.h
+ perl-libxml-mm.c

Makefile.PL
+ checks the utf8 capability of perl (-DHAVE_UTF8 is set if perl is at least
5.6.0)

LibXML.pm dom.c dom.h
t/01basic.t t/02parsestring.t t/05dombasic.t t/06nodetypes.t
t/07nodelist.t t/10ns.t
(---)

Added Files:
perl-libxml-mm.c perl-libxml-mm.h
+ implements the common logic of the MM (Perl <-> C layer)

  • Participants
  • Parent commits a6ff398

Comments (0)

Files changed (13)

 #ifdef __cplusplus
 extern "C" {
 #endif
+
+/* perl stuff */
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
+
+/* libxml2 stuff */
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xinclude.h>
 #include <libxml/valid.h>
 
+/* XML::LibXML stuff */
+#include "perl-libxml-mm.h"
+
 #include "dom.h"
 #include "xpath.h"
 
 #define TEST_PERL_FLAG(flag) \
     SvTRUE(perl_get_sv(flag, FALSE)) ? 1 : 0
 
-typedef struct _ProxyObject ProxyObject;
-
-struct _ProxyObject {
-    void * object;
-    SV * extra;
-    /* ProxyObject * next; */
-};
 
 static SV * LibXML_match_cb = NULL;
 static SV * LibXML_read_cb = NULL;
 /* this should keep the default */
 static xmlExternalEntityLoader LibXML_old_ext_ent_loader = NULL;
 
-ProxyObject *
-make_proxy_node (xmlNodePtr node)
-{
-    ProxyObject * proxy;
- 
-    proxy = (ProxyObject*)New(0, proxy, 1, ProxyObject);
-    if (proxy != NULL) {
-        proxy->object = (void*)node;
-        proxy->extra = NULL;
-    }
-    return proxy;
-}
-
 xmlParserInputPtr
 LibXML_load_external_entity(
         const char * URL, 
 
                 /* step 1: create the fragment */
                 fragment = xmlNewDocFragment( NULL );
-                # if ( !fragment ) warn( "no fragment!\n" );
-                ret = make_proxy_node( fragment );
-                RETVAL = NEWSV(0,0);
-                sv_setref_pv( RETVAL, (char *)CLASS, (void*)ret );
-                ret->extra = RETVAL;
-                # warn( "NEW FRAGMENT DOCUMENT" );
-                # SvREFCNT_inc(RETVAL);
+                RETVAL = nodeToSv(fragment);
+                setSvNodeExtra(RETVAL,RETVAL);
 
                 /* step 2: set the node list to the fragment */
                 fragment->children = rv;
                 rv->parent = fragment;
                 rv_end = rv;
-                while ( rv_end->next != NULL ) {
+                while ( rv_end != NULL ) {
+                    fragment->last = rv_end;
+                    rv_end->parent = fragment;
                     rv_end = rv_end->next;
-                    rv_end->parent = fragment;
                 }
-                fragment->last = rv_end;
             }
             else {
                 # warn( "bad chunk" );
-                RETVAL = &PL_sv_undef;
+                XSRETURN_UNDEF;
             }
             /* free the chunk we created */
             xmlFree( chunk );
 SV*
 encodeToUTF8( encoding, string )
         const char * encoding
-        const char * string
+        SV * string
     PREINIT:
-        char * tstr;
+        xmlChar * realstring;
+        xmlChar * tstr;
     CODE:
-        tstr =  domEncodeString( encoding, string );
-        RETVAL = newSVpvn( (char *)tstr, xmlStrlen( tstr ) );
-        xmlFree( tstr ); 
+        realstring = Sv2C(string,(xmlChar*) encoding);
+        RETVAL = C2Sv(realstring, NULL);
+        xmlFree( realstring );
+#ifdef HAVE_UTF8
+        SvUTF8_on(RETVAL);
+#endif
     OUTPUT:
         RETVAL
 
 SV*
 decodeFromUTF8( encoding, string ) 
         const char * encoding
-        const char * string
+        SV* string
     PREINIT:
-        char * tstr;
+        xmlChar * tstr;
+        xmlChar * realstring;
     CODE: 
-        tstr =  domDecodeString( encoding, string );
-        RETVAL = newSVpvn( (char *)tstr, xmlStrlen( tstr ) );
-        xmlFree( tstr ); 
+#ifdef HAVE_UTF8
+        if ( SvUTF8(string) ) {
+#endif
+        realstring = Sv2C(string,"UTF8" );
+        tstr =  domDecodeString( encoding, realstring );
+        RETVAL = C2Sv(tstr,(xmlChar*)encoding);
+        xmlFree( realstring ); 
+        xmlFree( tstr );
+#ifdef HAVE_UTF8
+        }
+#endif
     OUTPUT:
         RETVAL
 
 void
 _fix_extra(node_sv)
         SV * node_sv
-    PREINIT:
-        ProxyObject* node;
     CODE:
-        node = (ProxyObject *)SvIV((SV*)SvRV(node_sv));
-        node->extra = node_sv;
+        setSvNodeExtra(node_sv,node_sv);
 
 void
 DESTROY(self)
             # warn("%s, %d\n",result, len);
             RETVAL = newSVpvn((char *)result, (STRLEN)len);
             xmlFree(result);
+#ifdef HAVE_UTF8
+            xs_warn( "use utf8" );
+            SvUTF8_on(RETVAL);
+#endif
         }
     OUTPUT:
         RETVAL
         ProxyObject * ret= NULL;
     CODE:
         real_dom = domCreateDocument( version, encoding ); 
-        ret = make_proxy_node( (xmlNodePtr)real_dom );
-        RETVAL = NEWSV(0,0);
-        sv_setref_pv( RETVAL, (char *)CLASS, (void*)ret );
-        ret->extra = RETVAL;
+        RETVAL = nodeToSv((xmlNodePtr)real_dom);
+        setSvNodeExtra(RETVAL,RETVAL);
     OUTPUT:
         RETVAL
 
         SV * frag_sv = NULL;
         xmlDocPtr real_dom;
         xmlNodePtr fragment= NULL;
-        ProxyObject *ret=NULL;
-        const char * CLASS = "XML::LibXML::DocumentFragment";
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        fragment = xmlNewDocFragment( real_dom );
-        ret = make_proxy_node( fragment );
-        RETVAL = NEWSV(0,0);
-        sv_setref_pv( RETVAL, (char *)CLASS, (void*)ret );
-        ret->extra = RETVAL;
-        # warn( "NEW FRAGMENT DOCUMENT" );
-        SvREFCNT_inc(RETVAL);
+        real_dom = (xmlDocPtr)getSvNode(dom);
+        RETVAL = nodeToSv(xmlNewDocFragment( real_dom ));
+        setSvNodeExtra(RETVAL, RETVAL);
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV*
 createElement( dom, name )
         SV * dom
-        char* name
+        SV* name
     PREINIT:
-        char * CLASS = "XML::LibXML::Element";
-        xmlNodePtr newNode;
+        xmlNodePtr docfrag,newNode;
         xmlDocPtr real_dom;
-        xmlNodePtr docfrag = NULL;
-        ProxyObject * dfProxy= NULL;
         xmlChar * elname = NULL;
         SV * docfrag_sv = NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-
+        real_dom = (xmlDocPtr)getSvNode(dom);
         docfrag = xmlNewDocFragment( real_dom );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv = NEWSV(0,0);
-        sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        # warn( "NEW FRAGMENT ELEMNT (%s)", name);
-        //# SvREFCNT_inc(docfrag_sv);    
-
-        # warn("xmlNewNode\n");
-        if ( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ) {
-            elname = domEncodeString( real_dom->encoding, name);
+        docfrag_sv = nodeToSv(docfrag);
+        setSvNodeExtra(docfrag_sv, docfrag_sv);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(name) ) {
+#endif
+            elname = xmlStrdup(Sv2C(name,NULL));
+#ifdef HAVE_UTF8
         }
         else {
-            elname = xmlStrdup(name);
+            elname = Sv2C(name,real_dom->encoding);
         }
+#endif
         newNode = xmlNewNode(NULL , elname);
         xmlFree(elname);
         
         newNode->doc = real_dom;
         domAppendChild( docfrag, newNode );
         # warn( newNode->name );
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = docfrag_sv;
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,docfrag_sv);
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV*
 createElementNS( dom, nsURI, qname)
          SV * dom
          char *nsURI
-         char* qname 
+         SV* qname 
      PREINIT:
-         char * CLASS = "XML::LibXML::Element";
          xmlNodePtr newNode;
          xmlChar *prefix;
+         xmlChar* quali_name;
          xmlChar *lname = NULL;
          xmlNsPtr ns = NULL;
          xmlDocPtr real_dom;
          xmlNodePtr docfrag = NULL;
          xmlChar * encstring = NULL;
-         ProxyObject * dfProxy= NULL;
          SV * docfrag_sv = NULL;
      CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-
-        docfrag = xmlNewDocFragment( real_dom );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv = NEWSV(0,0);
-        sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        # warn( "NEW FRAGMENT ELEMENT NS (%s)", qname);
-        # SvREFCNT_inc(docfrag_sv);    
-
-        if ( nsURI != NULL && strlen(nsURI)!=0 ){
-            lname = xmlSplitQName2(qname, &prefix);
-            if ( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING" ) ) {
-                encstring = domEncodeString( real_dom->encoding, prefix );
-            }
-            else {
-                encstring = xmlStrdup( prefix );
-            }
-            ns = domNewNs (0 , encstring, nsURI );
-            xmlFree( encstring );
+        real_dom = (xmlDocPtr)getSvNode(dom);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(qname) ) {
+#endif
+            quali_name = Sv2C(qname,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            lname = qname;
+            quali_name = Sv2C(qname,real_dom->encoding);
         }
-
-        if ( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ) {
-            encstring = domEncodeString( real_dom->encoding, lname );
+#endif
+        docfrag = xmlNewDocFragment( real_dom );
+        docfrag_sv = nodeToSv(docfrag);
+        setSvNodeExtra(docfrag_sv, docfrag_sv);
+
+        if ( nsURI != NULL && strlen(nsURI)!=0 ){
+            lname = xmlSplitQName2(quali_name, &prefix);
+            ns = domNewNs (0 , prefix, nsURI );
         }
         else {
-            encstring = xmlStrdup( lname );
+            lname = quali_name;
         }
 
-        newNode = xmlNewNode( ns , encstring );
-        xmlFree(encstring);
+        newNode = xmlNewNode( ns , lname );
 
         newNode->doc = real_dom;
         domAppendChild( docfrag, newNode );
-
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = docfrag_sv;
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,docfrag_sv);
+        xmlFree(quali_name);
      OUTPUT:
         RETVAL
 
-ProxyObject *
+SV *
 createTextNode( dom, content )
         SV * dom
-        char * content
+        SV * content
     PREINIT:
-        char * CLASS = "XML::LibXML::Text";
         xmlNodePtr newNode;
         xmlDocPtr real_dom;
         xmlNodePtr docfrag = NULL;
-        ProxyObject * dfProxy= NULL;
         xmlChar * encstring = NULL;
         SV * docfrag_sv = NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-
+        real_dom = (xmlDocPtr)getSvNode(dom);
+ 
         docfrag = xmlNewDocFragment( real_dom );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv =sv_newmortal();
-        sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        # warn( "NEW FRAGMENT TEXT");
-        # SvREFCNT_inc(docfrag_sv);    
-
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ){
-            encstring = domEncodeString( real_dom->encoding, content );
+        docfrag_sv =nodeToSv(docfrag);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(content) ) {
+#endif
+            encstring = Sv2C(content,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            encstring = xmlStrdup( content );
+            encstring = Sv2C(content,real_dom->encoding);
         }
-
+#endif
         newNode = xmlNewDocText( real_dom, encstring );
         xmlFree(encstring);
+        newNode->doc = real_dom;
 
         domAppendChild( docfrag, newNode );
 
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = docfrag_sv;
-        SvREFCNT_inc(docfrag_sv);
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,docfrag_sv);
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV *
 createComment( dom , content )
         SV * dom
-        char * content
+        SV * content
     PREINIT:
-        char * CLASS = "XML::LibXML::Comment";
         xmlNodePtr newNode;
         xmlDocPtr real_dom;
         xmlNodePtr docfrag = NULL;
-        ProxyObject * dfProxy= NULL;
         SV * docfrag_sv = NULL;
-        char * encstr = NULL;
+        char * encstring = NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ){
-            encstr = domEncodeString( real_dom->encoding, content );
+        real_dom = (xmlDocPtr)getSvNode(dom);
+
+        docfrag = xmlNewDocFragment( real_dom );
+        docfrag_sv =nodeToSv(docfrag);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(content) ) {
+#endif
+            encstring = Sv2C(content,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            encstr = xmlStrdup( content );
-        }        
-
-        newNode = xmlNewDocComment( real_dom, encstr );
-        xmlFree( encstr );
-        docfrag = xmlNewDocFragment( real_dom );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv =sv_newmortal();
-        sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        # warn( "NEW FRAGMENT COMMENT");
-        # SvREFCNT_inc(docfrag_sv);    
+            encstring = Sv2C(content,real_dom->encoding);
+        }
+#endif
+        newNode = xmlNewDocComment( real_dom, encstring );
+        xmlFree( encstring );
+        newNode->doc = real_dom;
         domAppendChild( docfrag, newNode );
 
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = docfrag_sv;
-        SvREFCNT_inc(docfrag_sv);
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,docfrag_sv);
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV *
 createCDATASection( dom, content )
         SV * dom
-        char * content
+        SV * content
     PREINIT:
-        char * CLASS = "XML::LibXML::CDATASection";
         xmlNodePtr newNode;
         xmlDocPtr real_dom;
         xmlNodePtr docfrag = NULL;
-        ProxyObject * dfProxy= NULL;
         SV * docfrag_sv = NULL;
-        char * encstr = NULL;
+        xmlChar * encstring = NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") )
-            encstr = domEncodeString( real_dom->encoding, content );
-        else 
-            encstr = xmlStrdup( content );
-
-        newNode = domCreateCDATASection( real_dom, encstr );
-        xmlFree(encstr);        
-
+        real_dom = (xmlDocPtr)getSvNode(dom);
+ 
         docfrag = xmlNewDocFragment( real_dom );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv = sv_newmortal();
-        sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        # warn( "NEW FRAGMENT CDATA");
-        # SvREFCNT_inc(docfrag_sv);    
+        docfrag_sv =nodeToSv(docfrag);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(content) ) {
+#endif
+            encstring = Sv2C(content,NULL);
+#ifdef HAVE_UTF8
+        }
+        else {
+            encstring = Sv2C(content,real_dom->encoding);
+        }
+#endif
+        newNode = domCreateCDATASection( real_dom, encstring );
+        xmlFree(encstring);
+        newNode->doc = real_dom;
         domAppendChild( docfrag, newNode );
 
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = docfrag_sv;
-        SvREFCNT_inc(docfrag_sv);
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,docfrag_sv);
     OUTPUT:
         RETVAL
 
-ProxyObject *
-createAttribute( dom, name , value="" )
+SV *
+createAttribute( dom, name , value=&PL_sv_undef )
         SV * dom
-        char * name
-        char * value
+        SV * name
+        SV * value
     PREINIT:
-        const char* CLASS = "XML::LibXML::Attr";
         xmlNodePtr newNode;
         xmlDocPtr real_dom;
         xmlChar *encname = NULL;
         xmlChar *encval  = NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ){
-            encname  = domEncodeString( real_dom->encoding, name );
-            encval   = domEncodeString( real_dom->encoding, value );
+        real_dom = (xmlDocPtr)getSvNode(dom);  
+#ifdef HAVE_UTF8
+        if ( SvUTF8(name) ) {
+#endif
+            encname = Sv2C(name,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            encname = xmlStrdup( name );
-            encval  = xmlStrdup( value );
-        }    
+            encname = Sv2C(name,real_dom->encoding);
+        }
+#endif
+#ifdef HAVE_UTF8
+        if ( SvUTF8(value) ) {
+#endif
+            encval = Sv2C(value,NULL);
+#ifdef HAVE_UTF8
+        }
+        else {
+            encval = Sv2C(value,real_dom->encoding);
+        }
+#endif
+
         newNode = (xmlNodePtr)xmlNewProp(NULL, encname , encval );
         xmlFree(encname);
         xmlFree(encval);
 
-        newNode->doc = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
+        newNode->doc = real_dom;
         if ( newNode->children!=NULL ) {
-            newNode->children->doc = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
+            newNode->doc = real_dom;
         }
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = dom;
-        SvREFCNT_inc(dom);    
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,dom);  
     OUTPUT:
         RETVAL
 
-ProxyObject *
-createAttributeNS( dom, nsURI, qname, value="" )
+SV *
+createAttributeNS( dom, nsURI, qname, value=&PL_sv_undef )
         SV * dom
         char * nsURI
-        char * qname
-        char * value
+        SV * qname
+        SV * value
     PREINIT:
-        const char* CLASS = "XML::LibXML::Attr";
         xmlNodePtr newNode;
         xmlChar *prefix;
         xmlChar *lname =NULL;
-        xmlChar *enclname =NULL;
+        xmlChar *encname =NULL;
         xmlChar *encval =NULL;
         xmlNsPtr ns=NULL;
         xmlDocPtr real_dom;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        if ( nsURI != NULL && strlen( nsURI ) != 0 ){
-            lname = xmlSplitQName2(qname, &prefix);
+        real_dom = (xmlDocPtr)getSvNode(dom);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(qname) ) {
+#endif
+            encname = Sv2C(qname,NULL);
+#ifdef HAVE_UTF8
+        }
+        else {
+            encname = Sv2C(qname,real_dom->encoding);
+        }
+#endif
+         if ( nsURI != NULL && strlen( nsURI ) != 0 ){
+            lname = xmlSplitQName2(encname, &prefix);
             ns = domNewNs (0 , prefix , nsURI);
         }
         else{
-            lname = qname;
+            lname = encname;
         }
-    
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ){
-            enclname = domEncodeString( real_dom->encoding, lname );
-            encval = domEncodeString( real_dom->encoding, value );
+#ifdef HAVE_UTF8
+        if ( SvUTF8(value) ) {
+#endif
+            encval = Sv2C(value,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            enclname = xmlStrdup( lname );
-            encval   = xmlStrdup( value );
+            encval = Sv2C(value,real_dom->encoding);
         }
+#endif
         if ( ns != NULL ) {
-            newNode = (xmlNodePtr) xmlNewNsProp(NULL, ns, lname , value );
+            newNode = (xmlNodePtr) xmlNewNsProp(NULL, ns, lname , encval );
         }
         else {
-            newNode = (xmlNodePtr) xmlNewProp( NULL, lname, value );
+            newNode = (xmlNodePtr) xmlNewProp( NULL, lname, encval );
         }
         
         xmlFree(lname);
-        xmlFree(enclname);
+        xmlFree(encname);
         xmlFree(encval);
 
         newNode->doc = real_dom;
         if ( newNode->children!=NULL ) {
             newNode->children->doc = real_dom;
         }
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = dom;
-        SvREFCNT_inc(dom);    
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,dom);  
     OUTPUT:
         RETVAL
 
 void 
 setDocumentElement( dom , proxy )
         SV * dom
-        ProxyObject * proxy
+        SV * proxy
     PREINIT:
         xmlDocPtr real_dom;
         xmlNodePtr elem;
         SV* oldsv =NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        elem = (xmlNodePtr)proxy->object;
-
-        # please correct me if i am wrong: the document element HAS to be
-        # an ELEMENT NODE
+        real_dom = (xmlDocPtr)getSvNode(dom);
+        elem = getSvNode(proxy);
+
+        /* please correct me if i am wrong: the document element HAS to be
+         * an ELEMENT NODE
+         */ 
         if ( elem->type == XML_ELEMENT_NODE ) {
-            if( proxy->extra != NULL ) {
-                #warn( "decrease holder element" );
-                oldsv = proxy->extra;
-            }
             domSetDocumentElement( real_dom, elem );
-            proxy->extra = dom;
-            SvREFCNT_inc(dom);
-            SvREFCNT_dec( oldsv );
+            fix_proxy_extra(proxy, dom);            
         }
 
-ProxyObject *
+SV *
 getDocumentElement( dom )
         SV * dom
     ALIAS:
         XML::LibXML::Document::documentElement = 1
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr elem;
         xmlDocPtr real_dom;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        RETVAL = NULL;
+        real_dom = (xmlDocPtr)getSvNode(dom);
         elem = domDocumentElement( real_dom ) ;
         if ( elem ) {
-            CLASS = domNodeTypeName( elem );
-            RETVAL = make_proxy_node(elem);
-            RETVAL->extra = dom;
-            SvREFCNT_inc(dom);
+            RETVAL = nodeToSv(elem);
+            setSvNodeExtra(RETVAL,dom);  
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 void
 insertProcessingInstruction( dom, name, content )
         SV * dom
-        char * name 
-        char * content
+        SV * name 
+        SV * content
     ALIAS:
         insertPI = 1
     PREINIT:
         xmlChar * enctarg;
         xmlChar * encdata;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ){
-            enctarg = domEncodeString( real_dom->encoding, name );
-            encdata = domEncodeString( real_dom->encoding, content );
+        real_dom = (xmlDocPtr)getSvNode(dom);
+#ifdef HAVE_UTF8
+        if ( SvUTF8(name) ) {
+#endif
+            enctarg = Sv2C(name,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            enctarg = xmlStrdup( name );
-            encdata = xmlStrdup( content );
+            enctarg = Sv2C(name,real_dom->encoding);
         }
-
+#endif
+#ifdef HAVE_UTF8
+        if ( SvUTF8(content) ) {
+#endif
+            encdata = Sv2C(content,NULL);
+#ifdef HAVE_UTF8
+        }
+        else {
+            encdata = Sv2C(content,real_dom->encoding);
+        }
+#endif
         pinode = xmlNewPI( enctarg, encdata );
-        
         xmlFree(enctarg);
         xmlFree(encdata);
-
-        /* pinode = xmlNewPI( name, content ); */
         domInsertBefore( (xmlNodePtr)real_dom, 
                          pinode, 
                          domDocumentElement( real_dom ) );
 
-ProxyObject *
-createProcessingInstruction( dom, name, content="" )
+SV *
+createProcessingInstruction( dom, name, content=&PL_sv_undef )
         SV * dom
-        char * name 
-        char * content
+        SV * name 
+        SV * content
     ALIAS:
         createPI = 1
     PREINIT:
-        char * CLASS = "XML::LibXML::PI";
         xmlNodePtr newNode;
         xmlDocPtr real_dom;
         xmlNodePtr docfrag = NULL;
-        ProxyObject * dfProxy= NULL;
         xmlChar * enctarg;
         xmlChar * encdata;
         SV * docfrag_sv = NULL;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-
+        real_dom = (xmlDocPtr)getSvNode(dom);
         docfrag = xmlNewDocFragment( real_dom );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv =sv_newmortal();
-        sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        # warn( "NEW FRAGMENT ELEMNT (%s)", name);
-        # SvREFCNT_inc(docfrag_sv);    
-
-        if( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") ){
-            enctarg = domEncodeString( real_dom->encoding, name );
-            encdata = domEncodeString( real_dom->encoding, content );
+        docfrag_sv = nodeToSv((xmlNodePtr)docfrag );
+#ifdef HAVE_UTF8
+        if ( SvUTF8(name) ) {
+#endif
+            enctarg = Sv2C(name,NULL);
+#ifdef HAVE_UTF8
         }
         else {
-            enctarg = xmlStrdup( name );
-            encdata = xmlStrdup( content );
+            enctarg = Sv2C(name,real_dom->encoding);
         }
-
+#endif
+#ifdef HAVE_UTF8
+        if ( SvUTF8(content) ) {
+#endif
+            encdata = Sv2C(content,NULL);
+#ifdef HAVE_UTF8
+        }
+        else {
+            encdata = Sv2C(content,real_dom->encoding);
+        }
+#endif
         newNode = xmlNewPI( enctarg, encdata );
         xmlFree(enctarg);
         xmlFree(encdata);
         newNode->doc = real_dom;
         domAppendChild( docfrag, newNode );
         # warn( newNode->name );
-        RETVAL = make_proxy_node(newNode);
-        RETVAL->extra = docfrag_sv;
-        SvREFCNT_inc(docfrag_sv);
+        RETVAL = nodeToSv(newNode);
+        setSvNodeExtra(RETVAL,docfrag_sv);        
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV *
 importNode( dom, node, move=0 ) 
         SV * dom
-        ProxyObject * node
+        SV * node
         int move
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret = NULL;
         xmlNodePtr real_node = NULL;
         xmlDocPtr real_dom;
     CODE:
-        real_dom = (xmlDocPtr)((ProxyObject*)SvIV((SV*)SvRV(dom)))->object;
-        real_node= (xmlNodePtr)node->object;
-        RETVAL = NULL;
+        real_dom = (xmlDocPtr)getSvNode(dom);
+        real_node= getSvNode(node);
         ret = domImportNode( real_dom, real_node, move );
         if ( ret ) {
-            if ( node->extra != NULL && move == 0 ){
-                SvREFCNT_dec( node->extra );
+            RETVAL = nodeToSv(ret);
+            if ( move == 0 ){
+                fix_proxy_extra(RETVAL, dom);
             }
-            CLASS = domNodeTypeName( ret );
-            RETVAL = make_proxy_node(ret);
-            RETVAL->extra = dom;
-            SvREFCNT_inc(dom);
+            else {
+                setSvNodeExtra(RETVAL, dom);
+            } 
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
 char*
 getEncoding( self )
-        ProxyObject* self
+        SV* self
     CODE:
-        if( self != NULL && self->object!=NULL) {
-            RETVAL = xmlStrdup( ((xmlDocPtr)self->object)->encoding );
+        if( self != NULL && self!=&PL_sv_undef) {
+            RETVAL = xmlStrdup(((xmlDocPtr)getSvNode(self))->encoding );
         }
     OUTPUT:
         RETVAL
 
 void
 setEncoding( self, encoding )
-        ProxyObject* self
+        SV* self
         char *encoding
     CODE:
-        if( self != NULL && self->object!=NULL) {
-            ((xmlDocPtr)self->object)->encoding = xmlStrdup( encoding );
+        if( self != NULL && self!=&PL_sv_undef) {
+            ((xmlDocPtr)getSvNode(self))->encoding = xmlStrdup( encoding );
         }
 
 char*
 getVersion( self ) 
-         ProxyObject* self
+         SV * self
     CODE:
-        if( self != NULL && self->object != NULL) {
-            RETVAL = xmlStrdup( ((xmlDocPtr)self->object)->version );
+        if( self != NULL && self != &PL_sv_undef ) {
+            RETVAL = xmlStrdup( ((xmlDocPtr)getSvNode(self))->version );
         }
     OUTPUT:
         RETVAL
 
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::Dtd
 
-ProxyObject *
+SV *
 new(CLASS, external, system)
         char * CLASS
         char * external
         char * system
     CODE:
         LibXML_error = sv_2mortal(newSVpv("", 0));
-        RETVAL = make_proxy_node((xmlNodePtr)xmlParseDTD((const xmlChar*)external, (const xmlChar*)system));
+        RETVAL = nodeToSv((xmlNodePtr)xmlParseDTD((const xmlChar*)external, (const xmlChar*)system));
     OUTPUT:
         RETVAL
 
 
 void
 DESTROY( node )
-        ProxyObject * node
+        SV * node
     PREINIT:
+        SV* dom;
         xmlNodePtr real_node;
     CODE:
         /* XXX should destroy node->extra if refcnt == 0 */
-        if (node == NULL) {
-           XSRETURN_UNDEF;
-        }
-        real_node = (xmlNodePtr)node->object;
-        if ( node->extra != NULL
-             && real_node != NULL ){
-            if( real_node->type == XML_DOCUMENT_FRAG_NODE ) {
-                warn( "NODE DESTROY: NODE ISA DOCUMENT_FRAGMENT!" );
+        if (node != NULL || node != &PL_sv_undef ) {
+            real_node = getSvNode(node);
+            dom = getSvNodeExtra(node);
+            if ( dom != NULL && dom != &PL_sv_undef && real_node != NULL ) {
+                if ( SvREFCNT(dom) > 0 ){
+                    SvREFCNT_dec(dom);
+                }
+                free_proxy_node(node);
             }
-
-            if ( SvREFCNT( node->extra ) > 0 ){
-                SvREFCNT_dec(node->extra);
+            else {
+                XSRETURN_UNDEF;
             }
         }
-        Safefree(node);
+        else {
+            XSRETURN_UNDEF;
+        }
+
 
 int 
 getType( node ) 
 
 void
 unbindNode( proxyelem )
-        ProxyObject * proxyelem
+        SV* proxyelem
     PREINIT:
         xmlNodePtr elem       = NULL;
         xmlNodePtr docfrag    = NULL;
         ProxyObject * dfProxy = NULL;
         SV * docfrag_sv       = NULL;
     CODE:
-        elem = (xmlNodePtr)proxyelem->object;
+        elem = getSvNode(proxyelem);
         domUnbindNode( elem );
 
         docfrag = xmlNewDocFragment( elem->doc );
-        dfProxy = make_proxy_node( docfrag );
-        docfrag_sv =sv_newmortal();
-        sv_setref_pv( docfrag_sv,
-                      "XML::LibXML::DocumentFragment", 
-                      (void*)dfProxy );
-        dfProxy->extra = docfrag_sv;
-        #warn("NEW FRAGMENT ON NODE %s", elem->name);
-        # SvREFCNT_inc(docfrag_sv);    
-
+        docfrag_sv = nodeToSv( docfrag );
+        setSvNodeExtra( docfrag_sv, docfrag_sv );
+    
         domAppendChild( docfrag, elem );
-        if( proxyelem->extra != NULL ){
-            SvREFCNT_dec( proxyelem->extra );
-        }    
-        proxyelem->extra = docfrag_sv;
-        SvREFCNT_inc(docfrag_sv);             
-
-ProxyObject *
+        fix_proxy_extra( proxyelem, docfrag_sv );
+
+SV*
 removeChild( paren, child ) 
         xmlNodePtr paren
-        xmlNodePtr child
+        SV* child
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
-        xmlNodePtr ret;
+        SV* docfrag_sv;
+        xmlNodePtr ret, docfrag;
     CODE:
-        ret = domRemoveChild( paren, child );
-        RETVAL = NULL;
+        ret = domRemoveChild( paren, getSvNode(child) );
         if (ret != NULL) {
-            CLASS = domNodeTypeName( ret );
-            RETVAL = make_proxy_node(ret);
+            RETVAL = newSVsv(child);
+            docfrag = xmlNewDocFragment(paren->doc );
+            docfrag_sv = nodeToSv(docfrag);
+            setSvNodeExtra(docfrag_sv, docfrag_sv);
+            fix_proxy_extra(RETVAL,docfrag_sv);
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV*
 replaceChild( paren, newChild, oldChild ) 
-        ProxyObject* paren
-        ProxyObject* newChild
-        xmlNodePtr oldChild
+        SV* paren
+        SV* newChild
+        SV* oldChild
+    PREINIT:
+        SV* docfrag_sv;
+        xmlNodePtr pNode, nNode, oNode, docfrag;
+        xmlNodePtr ret;
+    CODE:
+        pNode = getSvNode( paren );
+        nNode = getSvNode( newChild );
+        oNode = getSvNode( oldChild );
+        ret = domReplaceChild( pNode, nNode, oNode );
+        if (ret != NULL) {
+            /* create document fragment */
+            docfrag = xmlNewDocFragment( pNode->doc );
+            docfrag_sv = nodeToSv(docfrag);
+            setSvNodeExtra(docfrag_sv, docfrag_sv);
+        
+            RETVAL = newSVsv(oldChild);
+
+            fix_proxy_extra(RETVAL,docfrag_sv);
+            fix_proxy_extra(newChild,getSvNodeExtra(paren));    
+        }
+        else {
+            XSRETURN_UNDEF;
+        }
+    OUTPUT:
+        RETVAL
+
+void
+appendChild( parent, child )
+        SV* parent
+        SV* child
     PREINIT:
         ProxyObject* pproxy = NULL;
         ProxyObject* cproxy = NULL;
-        const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr test = NULL, pNode, cNode;
+    CODE:
+        pNode = getSvNode(parent);
+        cNode = getSvNode(child);
+
+        if ( pNode == NULL ) {
+               croak("parent problem!\n");
+        }
+        if ( cNode == NULL ) {
+               croak("child problem!\n");
+        }
+
+        if (pNode->type == XML_DOCUMENT_NODE
+             && cNode->type == XML_ELEMENT_NODE ) {
+            /* silently ignore */
+            xs_warn( "use setDocumentElement!!!!\n" );
+        }
+        else {
+            if ( domAppendChild( pNode, cNode ) != NULL ) {
+                fix_proxy_extra( child, parent );
+            }
+            else {
+                xs_warn("append problem ...\n");
+            }
+        }
+
+SV*
+cloneNode( self, deep ) 
+        SV* self
+        int deep
+    PREINIT:
         xmlNodePtr ret;
+        xmlNodePtr docfrag = NULL;
+        SV * docfrag_sv = NULL;
+        xmlNodePtr realself = getSvNode(self);
     CODE:
-        ret = domReplaceChild( paren->object, newChild->object, oldChild );
-        RETVAL = NULL;
+        ret = xmlCopyNode( realself, deep );
         if (ret != NULL) {
-            CLASS = domNodeTypeName( ret );
-            RETVAL = make_proxy_node(ret);
+            docfrag = xmlNewDocFragment( ret->doc );
+            docfrag_sv =nodeToSv(docfrag);
+            domAppendChild( docfrag, ret );            
             
-            if ( ((xmlNodePtr)paren->object)->type == XML_DOCUMENT_NODE ) {
-                pproxy = paren;
-            }
-            else 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);
-                }
-            }
+            RETVAL = nodeToSv(ret);
+            fix_proxy_extra(RETVAL, docfrag_sv);
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
-void
-appendChild( parent, child )
-        ProxyObject* parent
-        ProxyObject* child
-    PREINIT:
-        ProxyObject* pproxy = NULL;
-        ProxyObject* cproxy = NULL;
-        xmlNodePtr test = NULL;
-    CODE:
-        if ( parent == NULL ) {
-               croak("parent problem!\n");
-        }
-        if ( child == NULL ) {
-               croak("child problem!\n");
-        }
-
-        # warn( "append Child \n" );
-        if (((xmlNodePtr)parent->object)->type == XML_DOCUMENT_NODE
-             && ((xmlNodePtr)child->object)->type == XML_ELEMENT_NODE ) {
-            # warn( "use setDocumentElement!!!!\n" );
-            
-        }
-        else {
-            # test = domAppendChild( parent->object, child->object );
-            # update the proxies if nessecary
-            # warn( "real append\n" );
-            if ( domAppendChild( parent->object, child->object ) != NULL ) {
-
-                # warn( "node appended\n" );    
-                /* if we appended a fragment we do not need to change refcounts */
-                if ( !((xmlNodePtr)parent->object)->type == XML_DOCUMENT_FRAG_NODE ) {
-                    if ( ((xmlNodePtr)parent->object)->type == XML_DOCUMENT_NODE ) {
-                        pproxy = parent;
-                    }
-                    else if ( parent->extra != NULL ){
-                        pproxy = (ProxyObject*)SvIV((SV*)SvRV(parent->extra));
-                    }
-
-                    if ( child->extra != NULL ) {
-                        # warn( "c1\n" );
-                        cproxy = (ProxyObject*)SvIV((SV*)SvRV(child->extra));
-                        # warn( "c2\n" );    
-                    }
-
-                    if ( child->extra == NULL
-                         || parent->extra == 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);
-                        }
-                    }
-                    else {
-                        # warn( "object failure\n" );
-                    }
-                }
-                else {
-                    # warn( "fragment append!\n" );
-                }
-            }
-            else {
-                # warn("append problem ...\n");
-            }
-        }
-
-ProxyObject *
-cloneNode( self, deep ) 
-        ProxyObject* self
-        int deep
-    PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
-        xmlNodePtr ret;
-        xmlNodePtr docfrag = NULL;
-        ProxyObject * dfProxy= NULL;
-        SV * docfrag_sv = NULL;
-    CODE:
-        ret = xmlCopyNode( (xmlNodePtr)self->object, deep );
-        RETVAL = NULL;
-        if (ret != NULL) {
-            docfrag = xmlNewDocFragment( ret->doc );
-            dfProxy = make_proxy_node( docfrag );
-            docfrag_sv =sv_newmortal();
-            sv_setref_pv( docfrag_sv, "XML::LibXML::DocumentFragment", (void*)dfProxy );
-            dfProxy->extra = docfrag_sv;
-            # warn( "NEW FRAGMENT CLONE");
-            # SvREFCNT_inc(docfrag_sv);    
-            domAppendChild( docfrag, ret );            
-
-            CLASS = domNodeTypeName( ret );
-            RETVAL = make_proxy_node(ret);
-            RETVAL->extra = docfrag_sv ;
-            SvREFCNT_inc(docfrag_sv);                
-        }
-    OUTPUT:
-        RETVAL
-
-
-ProxyObject *
+
+SV*
 getParentNode( self )
-        ProxyObject* self
+        SV* self
     ALIAS:
         XML::LibXML::Node::parentNode = 1
     PREINIT:
-        const char * CLASS = "XML::LibXML::Element";
         xmlNodePtr ret;
     CODE:
-        ret = ((xmlNodePtr)self->object)->parent;
-        RETVAL = NULL;
+        ret = getSvNode(self)->parent;
         if (ret != NULL) {
-            RETVAL = make_proxy_node(ret);
-            if( self->extra != NULL ) {
-                RETVAL->extra = self->extra ;
-                SvREFCNT_inc(self->extra);                
-            }
+            RETVAL = nodeToSv(ret);
+            setSvNodeExtra(RETVAL, getSvNodeExtra(self));
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV*
 getNextSibling( elem )
-        ProxyObject* elem
+        SV* elem
     ALIAS:
         XML::LibXML::Node::nextSibling = 1
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        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);                
-            }
+        ret = getSvNode(elem)->next ;
+        if ( ret != NULL ) {
+            RETVAL = nodeToSv(ret);
+            setSvNodeExtra(RETVAL, getSvNodeExtra(elem));
         }	
+        else {
+            XSRETURN_UNDEF;
+        }
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV*
 getPreviousSibling( elem )
-        ProxyObject* elem
+        SV * elem
     ALIAS:
         XML::LibXML::Node::previousSibling = 1
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        ret = ((xmlNodePtr)elem->object)->prev;
-        RETVAL = NULL;
+        ret = getSvNode(elem)->prev;
         if ( ret != NULL ) {
-            CLASS = domNodeTypeName( ret );
-            RETVAL = make_proxy_node(ret);
-            if( elem->extra != NULL ) {
-                RETVAL->extra = elem->extra ;
-                SvREFCNT_inc(elem->extra);                
-            }
+            RETVAL = nodeToSv(ret);
+            setSvNodeExtra(RETVAL, getSvNodeExtra(elem));
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
-ProxyObject *
+SV*
 getFirstChild( elem )
-        ProxyObject* elem
+        SV* elem
     ALIAS:
         XML::LibXML::Node::firstChild = 1
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        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);
-            }
+        ret = getSvNode(elem)->children;
+        if ( ret != NULL ) {
+            RETVAL = nodeToSv(ret);
+            setSvNodeExtra(RETVAL, getSvNodeExtra(elem));
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
 
-ProxyObject *
+SV*
 getLastChild( elem )
-        ProxyObject* elem
+        SV* elem
     ALIAS:
         XML::LibXML::Node::lastChild = 1
     PREINIT:
-        const char * CLASS = "XML::LibXML::Node";
         xmlNodePtr ret;
     CODE:
-        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);
-            }
+        ret = getSvNode(elem)->last;
+        if ( ret != NULL ) {
+            RETVAL = nodeToSv(ret);
+            setSvNodeExtra(RETVAL, getSvNodeExtra(elem));
+        }
+        else {
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
 void
 insertBefore( self, new, ref ) 
-        ProxyObject* self
-        ProxyObject* new
-        xmlNodePtr ref
+        SV* self
+        SV* new
+        SV* ref
     PREINIT:
-        ProxyObject* pproxy= NULL;
-        ProxyObject* cproxy= NULL; 
+        xmlNodePtr pNode, nNode, oNode;
     CODE:
-        if ( !(((xmlNodePtr)self->object)->type == XML_DOCUMENT_NODE
-             && ((xmlNodePtr)new->object)->type == XML_ELEMENT_NODE ) 
-             && domInsertBefore( self->object, new->object, ref ) != NULL ) {
-            if ( ((xmlNodePtr)self->object)->type == XML_DOCUMENT_NODE ) {
-                pproxy = self;
-            }
-            else if ( self->extra != NULL ){
-                pproxy = (ProxyObject*)SvIV((SV*)SvRV(self->extra));
-            }
-            if ( new->extra != NULL ) {
-                cproxy = (ProxyObject*)SvIV((SV*)SvRV(new->extra));
-            }
-            if ( pproxy->object != cproxy->object ) {
-      
-                # warn("different documents");
-                if ( new->extra != NULL ){
-                    # warn("decrease old child document");   
-                    SvREFCNT_dec(new->extra);
-                }
-
-                new->extra = self->extra;
-
-                if ( new->extra != NULL ){
-                    #warn("increase child document");   
-                    SvREFCNT_inc(new->extra);
-                }
-            }
+        pNode = getSvNode(self);
+        nNode = getSvNode(new);
+        oNode = getSvNode(ref);
+
+        if ( !(pNode->type == XML_DOCUMENT_NODE
+             && nNode->type == XML_ELEMENT_NODE ) 
+             && domInsertBefore( pNode, nNode, oNode ) != NULL ) {
+            fix_proxy_extra(new,getSvNodeExtra(self));
         }
 
 
 void
 insertAfter( self, new, ref )
-        ProxyObject* self
-        ProxyObject* new
-        xmlNodePtr ref
+        SV* self
+        SV* new
+        SV* ref
     PREINIT:
-        ProxyObject* pproxy= NULL;
-        ProxyObject* cproxy= NULL; 
+        xmlNodePtr pNode, nNode, oNode;
     CODE:
-        if ( !(((xmlNodePtr)self->object)->type == XML_DOCUMENT_NODE
-             && ((xmlNodePtr)new->object)->type == XML_ELEMENT_NODE ) 
-             && domInsertAfter( self->object, new->object, ref ) != NULL ) {
-            if ( ((xmlNodePtr)self->object)->type == XML_DOCUMENT_NODE ) {
-                pproxy = self;
-            }
-            else 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);
-                }
-            }
+        pNode = getSvNode(self);
+        nNode = getSvNode(new);
+        oNode = getSvNode(ref);
+
+        if ( !(pNode->type == XML_DOCUMENT_NODE
+             && nNode->type == XML_ELEMENT_NODE ) 
+             && domInsertAfter( pNode, nNode, oNode ) != NULL ) {
+            fix_proxy_extra(new,getSvNodeExtra(self));
         }
 
 SV*
 getOwnerDocument( elem )
-        ProxyObject* elem
+        SV* elem
     ALIAS:
         XML::LibXML::Node::ownerDocument = 1
+    PREINIT:
+        xmlNodePtr self = getSvNode(elem);
     CODE:
-        RETVAL = &PL_sv_undef;
-        if( ((xmlNodePtr)elem->object)->doc != NULL && elem->extra != NULL ){
-            RETVAL = elem->extra;
+        if( self != NULL
+            && self->doc != NULL
+            && getSvNodeExtra(elem) != NULL ){
+            RETVAL = getSvNodeExtra(elem);
             SvREFCNT_inc( RETVAL );
         }
+        else {
+            XSRETURN_UNDEF;
+        }
     OUTPUT:
         RETVAL
 
 SV*
 getOwner( elem ) 
-        ProxyObject * elem
+        SV* elem
     CODE:
-        RETVAL = &PL_sv_undef;
-        if( elem->extra != NULL ){
-            RETVAL = elem->extra;
+        if( getSvNodeExtra(elem) != NULL ){
+            RETVAL = getSvNodeExtra(elem);
             SvREFCNT_inc( RETVAL );
         }
+        else {
+            XSRETURN_UNDEF;
+        }
     OUTPUT:
         RETVAL
 
 void
 setOwnerDocument( elem, doc )
-        ProxyObject* elem
-        ProxyObject* doc
+        SV* elem
+        SV* doc
     PREINIT:
         xmlDocPtr real_doc;
     CODE:
-        real_doc = (xmlDocPtr)doc->object;
-        domSetOwnerDocument( elem->object, real_doc );
-        SvREFCNT_inc( doc->extra );
+        /* no increase here, because owner document is may not the root! */
+        real_doc = (xmlDocPtr)getSvNode(doc);
+        domSetOwnerDocument( getSvNode(elem), real_doc );
 
 SV*
 getName( node )
     CODE:
         if( node != NULL ) {
             name =  domName( node );
-            if( ( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") )
-                && ( node->doc != NULL ) ){
-                char* strDecoded;
-                strDecoded = domDecodeString( node->doc->encoding, name );
-                xmlFree( name );
-                name = strDecoded;
-            }
-            RETVAL = newSVpvn( (char *)name, xmlStrlen( name ) );
+            RETVAL = C2Sv(name,NULL);
             xmlFree( name );
         }
         else {
-            # warn( "got no node\n" );
-            RETVAL = &PL_sv_undef;
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 void
 setName( node , value )
         xmlNodePtr node
-        char * value
+        SV* value
+    PREINIT:
+        xmlChar* string;
     CODE:
-        if( (TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING")) 
-            && (node->doc != NULL) ){
-            xmlChar* strEncoded = domEncodeString( node->doc->encoding, value );
-            xmlFree( value );
-            value = strEncoded;
+#ifdef HAVE_UTF8
+        if ( SvUTF8(value) ) {
+#endif
+        string = Sv2C(value,NULL);
+#ifdef HAVE_UTF8
         }
-        domSetName( node, value );
+        else {
+            xmlChar* strEncoded = domEncodeString( node->doc->encoding, 
+                                                   Sv2C(value,NULL) );
+            xmlFree( string );
+            string = strEncoded;
+        }
+#endif
+        domSetName( node, string );
+        /* free the string here, too? */
+        xmlFree(string);
 
 SV*
 getData( proxy_node ) 
-        ProxyObject * proxy_node 
+        SV* proxy_node 
     ALIAS:
         XML::LibXML::Attr::value     = 1
         XML::LibXML::Node::nodeValue = 2
         XML::LibXML::Attr::getValue  = 3
     PREINIT:
         xmlNodePtr node;
-        char * content;
+        xmlChar * content = NULL;
     CODE:
-        node = (xmlNodePtr) proxy_node->object; 
+        /* this implementation is prolly b0rked!
+         * I have to go through the spec to find out what should
+         * be returned here.
+         */
+        xs_warn( "getDATA" );
+        node = getSvNode(proxy_node); 
 
         if( node != NULL ) {
             if ( node->type != XML_ATTRIBUTE_NODE ){
-                if ( ( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") )
-                     && ( node->doc != NULL ) ){
-                    content = domDecodeString( node->doc->encoding,
-                                               node->content );
-                }
-                else {
-                    content = xmlStrdup(node->content);
-                }
+                    if ( node->content != NULL ) {
+                        content = xmlStrdup(node->content);
+                    }
+                    else {
+                        if ( node->children != NULL ) {
+                            xmlNodePtr cnode = node->children;
+                            xs_warn ( "oh the node has children ..." );
+                            /* ok then toString in this case ... */
+                            while (cnode) {
+                                xmlBufferPtr buffer = xmlBufferCreate();
+                               /* buffer = xmlBufferCreate(); */
+                                xmlNodeDump( buffer, node->doc, cnode, 0, 0 );
+                                if ( buffer->content != NULL ) {
+                                    xs_warn( "add item" );
+                                    if ( content != NULL ) {
+                                        content = xmlStrcat( content, buffer->content );
+                                    }
+                                    else {
+                                        content = xmlStrdup( buffer->content );
+                                    }
+                                }
+                                xmlBufferFree( buffer );
+                                cnode = cnode->next;
+                            }
+                        }
+                    }                    
+             }
+            else if ( node->children != NULL ) {
+                xs_warn("copy kiddies content!");
+                content = xmlStrdup(node->children->content);
             }
-            else if ( node->children != NULL ) {
-                if ( ( TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING") )
-                     && ( node->doc != NULL ) ){
-                    content = domDecodeString( node->doc->encoding,
-                                               node->children->content );
-                }
-                else {
-                    content = xmlStrdup(node->children->content);
-                }
+            else {
+                xs_warn( "no bloddy data!" );
             }
         }
 
         if ( content != NULL ){
-            RETVAL = newSVpvn( (char *)content, xmlStrlen( content ) );
-            xmlFree( content );
+            xs_warn ( "content follows"); xs_warn( content );
+            RETVAL = C2Sv(content, NULL);
+            xmlFree(content);
         }
         else {
-            RETVAL = &PL_sv_undef;
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
 
 void
 _findnodes( node, xpath )
-        ProxyObject* node
+        SV* node
         char * xpath 
     PREINIT:
         xmlNodeSetPtr nodelist = NULL;
         SV * element = NULL ;
         int len = 0 ;
     PPCODE:
-        nodelist = domXPathSelect( node->object, xpath );
+        nodelist = domXPathSelect( getSvNode(node), xpath );
         if ( nodelist && nodelist->nodeNr > 0 ) {
             int i = 0 ;
             const char * cls = "XML::LibXML::Node";
             xmlNodePtr tnode;
-            ProxyObject * proxy;
             
             len = nodelist->nodeNr;
             for( i ; i < len; i++){
                  */
                 element = NULL;
                 tnode = nodelist->nodeTab[i];
-                element = sv_newmortal();
-                cls = domNodeTypeName( tnode );
 
                 if (tnode->type == XML_NAMESPACE_DECL) {
+                    element = sv_newmortal();
+                    cls = domNodeTypeName( tnode );
                     element = sv_setref_pv( element, (char *)cls, (void*)tnode );
                 } else {
-                    proxy = make_proxy_node(tnode);
-                    if ( node->extra != NULL ) {
-                        proxy->extra = node->extra;
-                        SvREFCNT_inc(node->extra);
-                    }
-                    element = sv_setref_pv( element, (char *)cls, (void*)proxy );
+                    element = nodeToSv(tnode);
+                    setSvNodeExtra(element, getSvNodeExtra(node));
                 }
                 XPUSHs( element );
-            }
-            
+            }            
             xmlXPathFreeNodeSet( nodelist );
         }
 
 void
 _find ( node, xpath )
-        ProxyObject* node
+        SV* node
         char * xpath
     PREINIT:
         xmlXPathObjectPtr found = NULL;
         xmlNodeSetPtr nodelist = NULL;
-        SV * element = NULL ;
+        SV* element = NULL ;
         int len = 0 ;
     PPCODE:
-        found = domXPathFind( node->object, xpath );
+        found = domXPathFind( getSvNode(node), xpath );
         if (found) {
             switch (found->type) {
                 case XPATH_NODESET:
                         int i = 0 ;
                         const char * cls = "XML::LibXML::Node";
                         xmlNodePtr tnode;
-                        ProxyObject * proxy;
                         SV * element;
                         
                         len = nodelist->nodeNr;
                         for( i ; i < len; i++){
-                           /* we have to create a new instance of an objectptr. and then 
-                             * place the current node into the new object. afterwards we can 
+                            /* we have to create a new instance of an
+                             * objectptr. and then
+                             * place the current node into the new
+                             * object. afterwards we can
                              * push the object to the array!
                              */
-                            element = NULL;
+
                             tnode = nodelist->nodeTab[i];
-                            element = sv_newmortal();
-                            cls = domNodeTypeName( tnode );
-            
-                            proxy = make_proxy_node(tnode);
-                            if ( node->extra != NULL
-                                 && ((xmlNodePtr)node->object)->type != XML_DOCUMENT_NODE ) {
-                                proxy->extra = node->extra;
-                                SvREFCNT_inc(node->extra);
-                            }
-                    
-                            element = sv_setref_pv( element, (char *)cls, (void*)proxy );
-                            cls = domNodeTypeName( tnode );
+                            element = nodeToSv(tnode);
+                            setSvNodeExtra(element,getSvNodeExtra(node));
+
                             XPUSHs( element );
                         }
                     }
                     XPUSHs(newSVpv(found->stringval, 0));
                     break;
                 default:
-                    croak("Uknown XPath return type");
+                    croak("Unknown XPath return type");
             }
             xmlXPathFreeObject(found);
         }
 
 void
 getChildnodes( node )
-        ProxyObject* node
+        SV* node
     ALIAS:
         XML::LibXML::Node::childNodes = 1
     PREINIT:
         xmlNodePtr cld;
         SV * element;
         int len = 0;
-        const char * cls = "XML::LibXML::Node";
-        ProxyObject * proxy;
         int wantarray = GIMME_V;
     PPCODE:
-        cld = ((xmlNodePtr)node->object)->children;
+        cld = getSvNode(node)->children;
+        xs_warn("childnodes start");
         while ( cld ) {
             if( wantarray != G_SCALAR ) {
-	            element = sv_newmortal();
-                cls = domNodeTypeName( cld );
-                proxy = make_proxy_node(cld);
-                if ( node->extra != NULL ) {
-                    proxy->extra = node->extra;
-                    SvREFCNT_inc(node->extra);
+                xs_warn("   --");
+                xs_warn(domNodeTypeName(cld));
+	            element = nodeToSv(cld);
+                if( cld->type == XML_PI_NODE ) {
+                    xs_warn("pi found!!!!");
                 }
-                element = sv_setref_pv( element, (char *)cls, (void*)proxy );
+                setSvNodeExtra(element, getSvNodeExtra(node));
+                xs_warn("   +-");
                 XPUSHs( element );
             }
+            xs_warn("   -+");
             cld = cld->next;
             len++;
         }
+        xs_warn("childnodes start");
         if ( wantarray == G_SCALAR ) {
             XPUSHs( newSViv(len) );
         }
         xmlNodeDump( buffer, self->doc, self, 0, 0 );
         if ( buffer->content != 0 ) {
             ret= xmlStrdup( buffer->content );
-            # warn( "x -> %s\n", ret );
         }
         xmlBufferFree( buffer );
-        
-        if ( (TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING")) 
-             && (self->doc != NULL) ) {
-            xmlChar *retDecoded = domDecodeString( self->doc->encoding, ret );
-            xmlFree( ret );
-            ret= retDecoded;
-        }
 
         if ( ret != NULL ) {
-            RETVAL = newSVpvn( ret , strlen( ret ) ) ;
+            RETVAL = C2Sv(ret, NULL) ;
             xmlFree( ret );
         }
         else {
 	        # warn("Failed to convert doc to string");           
-            RETVAL = &PL_sv_undef;
+            XSRETURN_UNDEF;
         }
     OUTPUT:
         RETVAL
         char * lname;
     CODE:
         if( node != NULL ) {
-            if ( (TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING")) 
-                 && (node->doc != NULL) ) {
-                lname = domDecodeString( node->doc->encoding, node->name );
-            }
-            else {
-                lname = xmlStrdup( node->name );
-            }
-            RETVAL = newSVpvn( (char *)lname, xmlStrlen( lname ) );
+            lname = xmlStrdup( node->name );
+            RETVAL = C2Sv(lname,NULL);
             xmlFree( lname );
         }
         else {
+            XSRETURN_UNDEF;
+        }
+    OUTPUT:
+        RETVAL
+
+SV*
+getPrefix( node )
+        xmlNodePtr node
+    ALIAS:
+        XML::LibXML::Node::prefix = 1
+    PREINIT:
+        xmlChar * prefix;
+    CODE:
+        if( node != NULL 
+            && node->ns != NULL
+            && node->ns->prefix != NULL ) {            
+            prefix = xmlStrdup(node->ns->prefix);
+            RETVAL = C2Sv(prefix, NULL);
+            xmlFree(prefix);
+        }
+        else {
+            XSRETURN_UNDEF;
+        }
+    OUTPUT:
+        RETVAL
+
+SV*
+getNamespaceURI( node )
+        xmlNodePtr node
+    PREINIT:
+        xmlChar * nsURI;
+    CODE:
+        if( node != NULL
+            && node->ns != NULL
+            && node->ns->href != NULL ) {
+            nsURI =  xmlStrdup(node->ns->href);
+            RETVAL = C2Sv(nsURI,NULL);
+            xmlFree(nsURI);
+        }
+        else {
             RETVAL = &PL_sv_undef;
         }
     OUTPUT:
         RETVAL
 
-SV*
-getPrefix( node )
-        xmlNodePtr node
-    ALIAS:
-        XML::LibXML::Node::prefix = 1
-    PREINIT:
-        char * prefix;
-    CODE:
-        if( node != NULL 
-            && node->ns != NULL
-            && node->ns->prefix != NULL ) {
-            if ( (TEST_PERL_FLAG("XML::LibXML::ORIGINAL_STRING")) 
-                 && (node->doc != NULL) ) {
-                prefix = domDecodeString( node->doc->encoding, 
-                                          node->ns->prefix );
-            }
-            else {
-                prefix =  xmlStrdup( node->ns->prefix );
-            }
-
-            RETVAL = newSVpvn( (char *)prefix, xmlStrlen( prefix ) );
-            xmlFree( prefix );
-        }
-        else {
-            RETVAL = &PL_sv_undef;
-        }
-    OUTPUT:
-        RETVAL
-
-SV*
-getNamespaceURI( node )
-        xmlNodePtr node
-    PREINIT:
-        const char * nsURI;
-    CODE:
-        if( node != NULL
-            && node->ns != NULL
-            && node->ns->href != NULL ) {
-            nsURI =  node->ns->href;
-            RETVAL = newSVpvn( (char *)nsURI, xmlStrlen( nsURI ) );
-        }
-        else {
-            RETVAL = &PL_sv_undef;
-        }
-    OUTPUT:
-        RETVAL
-
 int 
 hasAttributes( node ) 
-        ProxyObject * node
+        SV* node
+    PREINIT:
+        xmlNodePtr self = getSvNode(node);
     CODE:
         RETVAL = 0;
-        if( ((xmlNodePtr)node->object)->type == 1 
-            ||((xmlNodePtr)node->object)->type == 7
-            ||((xmlNodePtr)node->object)->type >= 9 ) {
-            if( ((xmlNodePtr)node->object)->properties != NULL ) {
+        if( self->type == 1 
+            ||self->type == 7
+            ||self->type >= 9 ) {
+
+            if( self->properties != NULL ) {
                 RETVAL = 1;
             }
         }
 
 void
 getAttributes( node )
-        ProxyObject* node
+        SV* node
     ALIAS:
         XML::LibXML::Node::attributes = 1
     PREINIT:
         const char * CLASS = "XML::LibXML::Attr";
         int wantarray = GIMME_V;
     PPCODE:
-        real_node = (xmlNodePtr) node->object;
+        real_node = getSvNode(node);
 
         attr      = real_node->properties;
         while ( attr != NULL ) {
-            ProxyObject * proxy=NULL;
             if ( wantarray != G_SCALAR ) {
-                element = sv_newmortal();   
-                proxy = make_proxy_node((xmlNodePtr)attr);
-                if ( node->extra != NULL ) {
-                    proxy->extra = node->extra;
-                    SvREFCNT_inc(node->extra);
-                }
-                XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)proxy ) );
+                element = nodeToSv((xmlNodePtr)attr);
+                setSvNodeExtra(element,getSvNodeExtra(node));
+                XPUSHs(element);
             }
             attr = attr->next;
             len++;
         while ( ns != NULL ) {
             const char * CLASS = "XML::LibXML::Namespace";
             if ( wantarray != G_SCALAR ) {
+                /* hmm this namespace handling looks odd ... */
                 element = sv_newmortal();
                 XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)ns ) );
             }
 
 void
 getAttributesNS( node,nsURI )
-        ProxyObject* node
+        SV* node
         char * nsURI
     PREINIT:
         xmlAttrPtr attr = NULL;
         const char * CLASS = "XML::LibXML::Attr";
         int wantarray = GIMME_V;
     PPCODE:
-        real_node = (xmlNodePtr) node->object;
+        real_node = (xmlNodePtr)getSvNode(node);
 
         attr      = real_node->properties;
         while ( attr != NULL ) {
             if( attr->ns != NULL && xmlStrcmp( nsURI, attr->ns->href ) == 0 ){ 
-                ProxyObject * proxy;
                 if( wantarray != G_SCALAR ) {
-                    element = sv_newmortal();
-                    
-                    proxy = make_proxy_node((xmlNodePtr)attr);
-                    if ( node->extra != NULL ) {
-                        proxy->extra = node->extra;
-                        SvREFCNT_inc(node->extra);
-                    }
-                    XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)proxy ) );
+                    element = nodeToSv((xmlNodePtr)attr);
+                    setSvNodeExtra(element,getSvNodeExtra(node));
+                    XPUSHs( element );
                 }
                 len++;
             }
         }
 
 void
-getNamespace ( node, prefix )
+getNamespace ( node, perlprefix )
         xmlNodePtr node
-        char * prefix
+        SV * perlprefix
     PREINIT:
+        xmlDocPtr real_dom= NULL;
+        xmlChar *prefix;
         xmlNsPtr ns = NULL;
         const char * CLASS = "XML::LibXML::Namespace";
         SV * element;
     PPCODE:
-        ns = node->nsDef;
-        while ( ns != NULL ) {
-            if (ns->prefix != NULL) {
-                if (strcmp(prefix, ns->prefix) == 0) {
-                    element = sv_newmortal();
-                    XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)ns ) );
-                    break;
+        if ( node != NULL && perlprefix != NULL && perlprefix != &PL_sv_undef ) {
+            real_dom = node->doc;
+            if ( real_dom != NULL ) {
+#ifdef HAVE_UTF8
+                if ( SvUTF8(perlprefix) ) {
+#endif
+                    prefix = Sv2C(perlprefix,NULL);
+#ifdef HAVE_UTF8
                 }
-            } else {
-                if (strlen(prefix) == 0) {
-                    element = sv_newmortal();
-                    XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)ns ) );
-                    break;
+                else {
+                    prefix = Sv2C(perlprefix,real_dom->encoding);
                 }
+#endif
             }
-            ns = ns->next;
+            else {
+                prefix = Sv2C(perlprefix,NULL);
+            }
+
+            ns = node->nsDef;
+            while ( ns != NULL ) {
+                if (ns->prefix != NULL) {
+                    if (xmlStrcmp(prefix, ns->prefix) == 0) {
+                        element = sv_newmortal();
+                        XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)ns ) );
+                        break;
+                    }
+                } else {
+                    if (xmlStrlen(prefix) == 0) {
+                        element = sv_newmortal();
+                        XPUSHs( sv_setref_pv( element, (char *)CLASS, (void*)ns ) );
+                        break;
+                    }
+                }
+                ns = ns->next;
+            }
+            xmlFree(prefix);
         }
 
-char *
+SV*
 string_value ( node )
         xmlNodePtr node
     ALIAS:
         to_literal = 1
     CODE:
-        RETVAL = xmlXPathCastNodeToString(node);
+        /* we can't just return a string, because of UTF8! */
+        RETVAL = C2Sv(xmlXPathCastNodeToString(node), NULL);
     OUTPUT:
         RETVAL
 
         
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::Element
 
-ProxyObject *
+SV*
 new(CLASS, name )
         char * CLASS