Make each IXMLDOMNode interface represent one libxml2 xmlNodePtr.

This commit is contained in:
Mike McCormack 2005-08-18 10:48:13 +00:00 committed by Alexandre Julliard
parent 5b5e5086d7
commit 23f192d299
5 changed files with 188 additions and 133 deletions

View File

@ -53,6 +53,11 @@ static inline domdoc *impl_from_IXMLDOMDocument( IXMLDOMDocument *iface )
return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl)); return (domdoc *)((char*)iface - FIELD_OFFSET(domdoc, lpVtbl));
} }
static inline xmlDocPtr get_doc( domdoc *This )
{
return (xmlDocPtr) xmlNodePtr_from_domnode( This->node, XML_DOCUMENT_NODE );
}
static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument *iface, REFIID riid, void** ppvObject ) static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument *iface, REFIID riid, void** ppvObject )
{ {
domdoc *This = impl_from_IXMLDOMDocument( iface ); domdoc *This = impl_from_IXMLDOMDocument( iface );
@ -503,7 +508,6 @@ static HRESULT WINAPI domdoc_get_documentElement(
domdoc *This = impl_from_IXMLDOMDocument( iface ); domdoc *This = impl_from_IXMLDOMDocument( iface );
xmlDocPtr xmldoc = NULL; xmlDocPtr xmldoc = NULL;
xmlNodePtr root = NULL; xmlNodePtr root = NULL;
IXMLDOMElement* element;
TRACE("%p\n", This); TRACE("%p\n", This);
@ -512,7 +516,7 @@ static HRESULT WINAPI domdoc_get_documentElement(
if ( !This->node ) if ( !This->node )
return S_FALSE; return S_FALSE;
xmldoc = xmldoc_from_xmlnode( This->node ); xmldoc = get_doc( This );
if ( !xmldoc ) if ( !xmldoc )
return S_FALSE; return S_FALSE;
@ -520,12 +524,7 @@ static HRESULT WINAPI domdoc_get_documentElement(
if ( !root ) if ( !root )
return S_FALSE; return S_FALSE;
element = create_element( root ); *DOMElement = create_element( root );
if ( element )
{
IXMLDOMNode_AddRef( This->node );
*DOMElement = element;
}
return S_OK; return S_OK;
} }

View File

@ -52,6 +52,11 @@ static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpVtbl)); return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpVtbl));
} }
static inline xmlNodePtr get_element( domelem *This )
{
return xmlNodePtr_from_domnode( This->node, XML_ELEMENT_NODE );
}
static HRESULT WINAPI domelem_QueryInterface( static HRESULT WINAPI domelem_QueryInterface(
IXMLDOMElement *iface, IXMLDOMElement *iface,
REFIID riid, REFIID riid,
@ -137,16 +142,16 @@ static HRESULT WINAPI domelem_get_nodeName(
IXMLDOMElement *iface, IXMLDOMElement *iface,
BSTR* p ) BSTR* p )
{ {
FIXME("\n"); domelem *This = impl_from_IXMLDOMElement( iface );
return E_NOTIMPL; return IXMLDOMNode_get_nodeName( This->node, p );
} }
static HRESULT WINAPI domelem_get_nodeValue( static HRESULT WINAPI domelem_get_nodeValue(
IXMLDOMElement *iface, IXMLDOMElement *iface,
VARIANT* var1 ) VARIANT* var1 )
{ {
FIXME("\n"); domelem *This = impl_from_IXMLDOMElement( iface );
return E_NOTIMPL; return IXMLDOMNode_get_nodeValue( This->node, var1 );
} }
static HRESULT WINAPI domelem_put_nodeValue( static HRESULT WINAPI domelem_put_nodeValue(
@ -161,8 +166,8 @@ static HRESULT WINAPI domelem_get_nodeType(
IXMLDOMElement *iface, IXMLDOMElement *iface,
DOMNodeType* domNodeType ) DOMNodeType* domNodeType )
{ {
FIXME("\n"); domelem *This = impl_from_IXMLDOMElement( iface );
return E_NOTIMPL; return IXMLDOMNode_get_nodeType( This->node, domNodeType );
} }
static HRESULT WINAPI domelem_get_parentNode( static HRESULT WINAPI domelem_get_parentNode(
@ -177,8 +182,8 @@ static HRESULT WINAPI domelem_get_childNodes(
IXMLDOMElement *iface, IXMLDOMElement *iface,
IXMLDOMNodeList** outList) IXMLDOMNodeList** outList)
{ {
FIXME("\n"); domelem *This = impl_from_IXMLDOMElement( iface );
return E_NOTIMPL; return IXMLDOMNode_get_childNodes( This->node, outList );
} }
static HRESULT WINAPI domelem_get_firstChild( static HRESULT WINAPI domelem_get_firstChild(
@ -217,8 +222,8 @@ static HRESULT WINAPI domelem_get_attributes(
IXMLDOMElement *iface, IXMLDOMElement *iface,
IXMLDOMNamedNodeMap** attributeMap) IXMLDOMNamedNodeMap** attributeMap)
{ {
FIXME("\n"); domelem *This = impl_from_IXMLDOMElement( iface );
return E_NOTIMPL; return IXMLDOMNode_get_attributes( This->node, attributeMap );
} }
static HRESULT WINAPI domelem_insertBefore( static HRESULT WINAPI domelem_insertBefore(
@ -412,8 +417,8 @@ static HRESULT WINAPI domelem_get_baseName(
IXMLDOMElement *iface, IXMLDOMElement *iface,
BSTR* p) BSTR* p)
{ {
FIXME("\n"); domelem *This = impl_from_IXMLDOMElement( iface );
return E_NOTIMPL; return IXMLDOMNode_get_baseName( This->node, p );
} }
static HRESULT WINAPI domelem_transformNodeToObject( static HRESULT WINAPI domelem_transformNodeToObject(
@ -436,7 +441,7 @@ static HRESULT WINAPI domelem_get_tagName(
if ( !This->node ) if ( !This->node )
return E_FAIL; return E_FAIL;
element = xmlelement_from_xmlnode( This->node ); element = get_element( This );
if ( !element ) if ( !element )
return E_FAIL; return E_FAIL;

View File

@ -36,10 +36,12 @@ extern IXMLDOMNode *create_attribute_node( xmlAttrPtr attr );
extern IUnknown *create_xmldoc( void ); extern IUnknown *create_xmldoc( void );
extern IXMLDOMElement *create_element( xmlNodePtr element ); extern IXMLDOMElement *create_element( xmlNodePtr element );
extern IXMLDOMNode *create_element_node( xmlNodePtr element ); extern IXMLDOMNode *create_element_node( xmlNodePtr element );
extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node );
extern IXMLDOMNode *create_generic_node( xmlNodePtr node );
extern IXMLDOMNodeList *create_nodelist( xmlNodePtr node );
/* data accessors */ /* data accessors */
extern xmlDocPtr xmldoc_from_xmlnode( IXMLDOMNode *iface ); xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type );
extern xmlNodePtr xmlelement_from_xmlnode( IXMLDOMNode *iface );
/* helpers */ /* helpers */
extern xmlChar *xmlChar_from_wchar( LPWSTR str ); extern xmlChar *xmlChar_from_wchar( LPWSTR str );

View File

@ -23,6 +23,7 @@
#define COBJMACROS #define COBJMACROS
#include <stdarg.h> #include <stdarg.h>
#include <assert.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winuser.h" #include "winuser.h"
@ -41,20 +42,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
typedef union {
xmlDocPtr doc;
xmlNodePtr node;
xmlAttrPtr attr;
xmlElementPtr element;
} libxml_node;
typedef struct _xmlnode typedef struct _xmlnode
{ {
const struct IXMLDOMNodeVtbl *lpVtbl; const struct IXMLDOMNodeVtbl *lpVtbl;
LONG ref; LONG ref;
BOOL free_me; xmlNodePtr node;
xmlElementType type;
libxml_node u;
} xmlnode; } xmlnode;
static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface ) static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
@ -62,25 +54,18 @@ static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface )
return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl)); return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl));
} }
xmlDocPtr xmldoc_from_xmlnode( IXMLDOMNode *iface ) xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type )
{ {
xmlnode *This; xmlnode *This;
if ( !iface ) if ( !iface )
return NULL; return NULL;
This = impl_from_IXMLDOMNode( iface ); This = impl_from_IXMLDOMNode( iface );
if (This->type != XML_DOCUMENT_NODE ) if ( !This->node )
return NULL; return NULL;
return This->u.doc; if ( type && This->node->type != type )
}
xmlNodePtr xmlelement_from_xmlnode( IXMLDOMNode *iface )
{
xmlnode *This = impl_from_IXMLDOMNode( iface );
if (This->type != XML_ELEMENT_NODE )
return NULL; return NULL;
return This->u.node; return This->node;
} }
static HRESULT WINAPI xmlnode_QueryInterface( static HRESULT WINAPI xmlnode_QueryInterface(
@ -120,20 +105,18 @@ static ULONG WINAPI xmlnode_Release(
ref = InterlockedDecrement( &This->ref ); ref = InterlockedDecrement( &This->ref );
if ( ref == 0 ) if ( ref == 0 )
{ {
if ( This->free_me ) if( This->node->type == XML_DOCUMENT_NODE )
{ {
switch( This->type ) xmlFreeDoc( (xmlDocPtr) This->node );
{ }
case XML_DOCUMENT_NODE: else
xmlFreeDoc( This->u.doc ); {
break; IXMLDOMNode *root;
case XML_ATTRIBUTE_NODE: assert( This->node->doc );
case XML_ELEMENT_NODE: root = This->node->doc->_private;
/* don't free these */ assert( root );
break; IXMLDOMNode_Release( root );
default: This->node->_private = NULL;
ERR("don't know how to free this element\n");
}
} }
HeapFree( GetProcessHeap(), 0, This ); HeapFree( GetProcessHeap(), 0, This );
} }
@ -218,33 +201,37 @@ static HRESULT WINAPI xmlnode_get_nodeValue(
VARIANT* value) VARIANT* value)
{ {
xmlnode *This = impl_from_IXMLDOMNode( iface ); xmlnode *This = impl_from_IXMLDOMNode( iface );
HRESULT r = S_FALSE;
TRACE("%p %p\n", This, value); TRACE("%p %p\n", This, value);
switch ( This->type ) V_BSTR(value) = NULL;
V_VT(value) = VT_NULL;
switch ( This->node->type )
{ {
case XML_COMMENT_NODE:
FIXME("comment\n");
return E_FAIL;
break;
case XML_ATTRIBUTE_NODE: case XML_ATTRIBUTE_NODE:
V_VT(value) = VT_BSTR; V_VT(value) = VT_BSTR;
V_BSTR(value) = bstr_from_xmlChar( This->u.attr->name ); V_BSTR(value) = bstr_from_xmlChar( This->node->name );
r = S_OK;
break; break;
case XML_PI_NODE: case XML_TEXT_NODE:
FIXME("processing instruction\n"); V_VT(value) = VT_BSTR;
return E_FAIL; V_BSTR(value) = bstr_from_xmlChar( This->node->content );
r = S_OK;
break; break;
case XML_ELEMENT_NODE: case XML_ELEMENT_NODE:
case XML_DOCUMENT_NODE: case XML_DOCUMENT_NODE:
default: /* these seem to return NULL */
return E_FAIL;
break; break;
case XML_PI_NODE:
default:
FIXME("node %p type %d\n", This, This->node->type);
} }
TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) ); TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) );
return S_OK; return r;
} }
static HRESULT WINAPI xmlnode_put_nodeValue( static HRESULT WINAPI xmlnode_put_nodeValue(
@ -259,8 +246,16 @@ static HRESULT WINAPI xmlnode_get_nodeType(
IXMLDOMNode *iface, IXMLDOMNode *iface,
DOMNodeType* type) DOMNodeType* type)
{ {
FIXME("\n"); xmlnode *This = impl_from_IXMLDOMNode( iface );
return E_NOTIMPL;
TRACE("%p %p\n", This, type);
assert( NODE_ELEMENT == XML_ELEMENT_NODE );
assert( NODE_NOTATION == XML_NOTATION_NODE );
*type = This->node->type;
return S_OK;
} }
static HRESULT WINAPI xmlnode_get_parentNode( static HRESULT WINAPI xmlnode_get_parentNode(
@ -276,9 +271,17 @@ static HRESULT WINAPI xmlnode_get_childNodes(
IXMLDOMNodeList** childList) IXMLDOMNodeList** childList)
{ {
xmlnode *This = impl_from_IXMLDOMNode( iface ); xmlnode *This = impl_from_IXMLDOMNode( iface );
FIXME("%p\n", This);
TRACE("%p %p\n", This, childList );
if ( !childList )
return E_INVALIDARG;
#if 0
*childList = create_nodelist( This->node->children );
return S_OK;
#else
return E_NOTIMPL; return E_NOTIMPL;
/*return NodeList_create( childList, This );*/ #endif
} }
static HRESULT WINAPI xmlnode_get_firstChild( static HRESULT WINAPI xmlnode_get_firstChild(
@ -318,9 +321,9 @@ static HRESULT WINAPI xmlnode_get_attributes(
IXMLDOMNamedNodeMap** attributeMap) IXMLDOMNamedNodeMap** attributeMap)
{ {
xmlnode *This = impl_from_IXMLDOMNode( iface ); xmlnode *This = impl_from_IXMLDOMNode( iface );
FIXME("%p\n", This); TRACE("%p\n", This);
return E_NOTIMPL; *attributeMap = create_nodemap( iface );
/*return NodeMap_create( attributeMap, This, node ); */ return S_OK;
} }
static HRESULT WINAPI xmlnode_insertBefore( static HRESULT WINAPI xmlnode_insertBefore(
@ -398,8 +401,23 @@ static HRESULT WINAPI xmlnode_get_text(
IXMLDOMNode *iface, IXMLDOMNode *iface,
BSTR* text) BSTR* text)
{ {
FIXME("\n"); xmlnode *This = impl_from_IXMLDOMNode( iface );
return E_NOTIMPL; xmlNodePtr child;
BSTR str = NULL;
TRACE("%p\n", This);
if ( !text )
return E_INVALIDARG;
child = This->node->children;
if ( child && child->type == XML_TEXT_NODE )
str = bstr_from_xmlChar( child->content );
TRACE("%p %s\n", This, debugstr_w(str) );
*text = str;
return S_OK;
} }
static HRESULT WINAPI xmlnode_put_text( static HRESULT WINAPI xmlnode_put_text(
@ -521,8 +539,33 @@ static HRESULT WINAPI xmlnode_get_baseName(
IXMLDOMNode *iface, IXMLDOMNode *iface,
BSTR* nameString) BSTR* nameString)
{ {
FIXME("\n"); xmlnode *This = impl_from_IXMLDOMNode( iface );
return E_NOTIMPL; BSTR str = NULL;
HRESULT r = S_FALSE;
TRACE("%p %p\n", This, nameString );
if ( !nameString )
return E_INVALIDARG;
switch ( This->node->type )
{
case XML_ELEMENT_NODE:
case XML_ATTRIBUTE_NODE:
str = bstr_from_xmlChar( This->node->name );
r = S_OK;
break;
case XML_TEXT_NODE:
break;
default:
ERR("Unhandled type %d\n", This->node->type );
break;
}
TRACE("returning %08lx str = %s\n", r, debugstr_w( str ) );
*nameString = str;
return r;
} }
static HRESULT WINAPI xmlnode_transformNodeToObject( static HRESULT WINAPI xmlnode_transformNodeToObject(
@ -581,71 +624,70 @@ static const struct IXMLDOMNodeVtbl xmlnode_vtbl =
xmlnode_transformNodeToObject, xmlnode_transformNodeToObject,
}; };
static xmlnode *create_node( void ) static IXMLDOMNode *create_node( xmlNodePtr node )
{ {
xmlnode *This; xmlnode *This;
if ( !node )
return NULL;
assert( node->doc );
/* if an interface already exists for this node, return it */
if ( node->_private )
{
IXMLDOMNode *n = node->_private;
IXMLDOMNode_AddRef( n );
return n;
}
/*
* Try adding a reference to the IXMLDOMNode implementation
* containing the document's root element.
*/
if ( node->type != XML_DOCUMENT_NODE )
{
IXMLDOMNode *root = NULL;
root = node->doc->_private;
assert( root );
IXMLDOMNode_AddRef( root );
}
else
assert( node->doc == (xmlDocPtr) node );
This = HeapAlloc( GetProcessHeap(), 0, sizeof *This ); This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
if ( !This ) if ( !This )
return NULL; return NULL;
This->lpVtbl = &xmlnode_vtbl; This->lpVtbl = &xmlnode_vtbl;
This->ref = 1; This->ref = 1;
This->free_me = TRUE; This->node = node;
This->u.doc = NULL;
return This; /* remember which interface we associated with this node */
node->_private = This;
return (IXMLDOMNode*) &This->lpVtbl;
} }
IXMLDOMNode *create_domdoc_node( xmlDocPtr node ) IXMLDOMNode *create_domdoc_node( xmlDocPtr node )
{ {
xmlnode *This; return create_node( (xmlNodePtr) node );
if ( !node )
return NULL;
This = create_node();
if ( !This )
return NULL;
This->type = XML_DOCUMENT_NODE;
This->u.doc = node;
return (IXMLDOMNode*) &This->lpVtbl;
} }
IXMLDOMNode *create_attribute_node( xmlAttrPtr node ) IXMLDOMNode *create_attribute_node( xmlAttrPtr node )
{ {
xmlnode *This; return create_node( (xmlNodePtr) node );
if ( !node )
return NULL;
This = create_node();
if ( !This )
return NULL;
This->type = XML_ATTRIBUTE_NODE;
This->u.attr = node;
return (IXMLDOMNode*) &This->lpVtbl;
} }
IXMLDOMNode *create_element_node( xmlNodePtr element ) IXMLDOMNode *create_element_node( xmlNodePtr element )
{ {
xmlnode *This; return create_node( element );
}
if ( !element ) IXMLDOMNode *create_generic_node( xmlNodePtr node )
return NULL; {
return create_node( node );
This = create_node();
if ( !This )
return NULL;
This->type = XML_ELEMENT_NODE;
This->u.node = element;
return (IXMLDOMNode*) &This->lpVtbl;
} }
#endif #endif

View File

@ -45,8 +45,7 @@ typedef struct _xmlnodemap
{ {
const struct IXMLDOMNamedNodeMapVtbl *lpVtbl; const struct IXMLDOMNamedNodeMapVtbl *lpVtbl;
LONG ref; LONG ref;
xmlDocPtr xmldoc; IXMLDOMNode *node;
xmlNodePtr node;
} xmlnodemap; } xmlnodemap;
static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface ) static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface )
@ -91,6 +90,7 @@ static ULONG WINAPI xmlnodemap_Release(
ref = InterlockedDecrement( &This->ref ); ref = InterlockedDecrement( &This->ref );
if ( ref == 0 ) if ( ref == 0 )
{ {
IXMLDOMNode_Release( This->node );
HeapFree( GetProcessHeap(), 0, This ); HeapFree( GetProcessHeap(), 0, This );
} }
@ -153,16 +153,24 @@ static HRESULT WINAPI xmlnodemap_getNamedItem(
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlChar *element_name; xmlChar *element_name;
xmlAttrPtr attr; xmlAttrPtr attr;
xmlNodePtr node;
TRACE("%p %s\n", This, debugstr_w(name) );
node = xmlNodePtr_from_domnode( This->node, 0 );
if ( !node )
return E_FAIL;
element_name = xmlChar_from_wchar( name ); element_name = xmlChar_from_wchar( name );
attr = xmlHasNsProp( This->node, element_name, NULL ); attr = xmlHasNsProp( node, element_name, NULL );
TRACE("xmlHasNsProp returned %p for %s\n", attr, element_name );
HeapFree( GetProcessHeap(), 0, element_name ); HeapFree( GetProcessHeap(), 0, element_name );
if ( !attr ) if ( !attr )
return E_FAIL; return E_FAIL;
/* return Node_create( namedItem, This->xmldoc, attr ); */
return E_NOTIMPL; *namedItem = create_attribute_node( attr );
return S_OK;
} }
static HRESULT WINAPI xmlnodemap_setNamedItem( static HRESULT WINAPI xmlnodemap_setNamedItem(
@ -264,22 +272,21 @@ static const struct IXMLDOMNamedNodeMapVtbl xmlnodemap_vtbl =
xmlnodemap__newEnum, xmlnodemap__newEnum,
}; };
HRESULT NodeMap_create( IXMLDOMNamedNodeMap** DomNamedNodeMap, xmlDocPtr xmldoc, xmlNodePtr node ) IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node )
{ {
xmlnodemap *nodemap; xmlnodemap *nodemap;
nodemap = HeapAlloc( GetProcessHeap(), 0, sizeof *nodemap ); nodemap = HeapAlloc( GetProcessHeap(), 0, sizeof *nodemap );
if ( !nodemap ) if ( !nodemap )
return E_OUTOFMEMORY; return NULL;
nodemap->lpVtbl = &xmlnodemap_vtbl; nodemap->lpVtbl = &xmlnodemap_vtbl;
nodemap->xmldoc = xmldoc;
nodemap->node = node; nodemap->node = node;
nodemap->ref = 1; nodemap->ref = 1;
*DomNamedNodeMap = (IXMLDOMNamedNodeMap*) &nodemap->lpVtbl; IXMLDOMNode_AddRef( node );
return S_OK; return (IXMLDOMNamedNodeMap*) &nodemap->lpVtbl;
} }
#endif #endif