Commit b6d3068c authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Support multiple IXMLDOMNamedNodeMap implementations.

parent d2236db8
......@@ -53,6 +53,8 @@ typedef struct _domelem
LONG ref;
} domelem;
static const struct nodemap_funcs domelem_attr_map;
static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
{
return CONTAINING_RECORD(iface, domelem, IXMLDOMElement_iface);
......@@ -320,7 +322,7 @@ static HRESULT WINAPI domelem_get_attributes(
TRACE("(%p)->(%p)\n", This, map);
*map = create_nodemap(This->node.node);
*map = create_nodemap(This->node.node, &domelem_attr_map);
return S_OK;
}
......@@ -1382,6 +1384,265 @@ static const struct IXMLDOMElementVtbl domelem_vtbl =
domelem_normalize,
};
static HRESULT domelem_get_qualified_item(const xmlNodePtr node, BSTR name, BSTR uri,
IXMLDOMNode **item)
{
xmlAttrPtr attr;
xmlChar *nameA;
xmlChar *href;
TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
if (!name || !item) return E_INVALIDARG;
if (uri && *uri)
{
href = xmlchar_from_wchar(uri);
if (!href) return E_OUTOFMEMORY;
}
else
href = NULL;
nameA = xmlchar_from_wchar(name);
if (!nameA)
{
heap_free(href);
return E_OUTOFMEMORY;
}
attr = xmlHasNsProp(node, nameA, href);
heap_free(nameA);
heap_free(href);
if (!attr)
{
*item = NULL;
return S_FALSE;
}
*item = create_node((xmlNodePtr)attr);
return S_OK;
}
static HRESULT domelem_get_named_item(const xmlNodePtr node, BSTR name, IXMLDOMNode **item)
{
xmlChar *nameA, *local, *prefix;
BSTR uriW, localW;
xmlNsPtr ns;
HRESULT hr;
TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item );
nameA = xmlchar_from_wchar(name);
local = xmlSplitQName2(nameA, &prefix);
heap_free(nameA);
if (!local)
return domelem_get_qualified_item(node, name, NULL, item);
/* try to get namespace uri for supplied qualified name */
ns = xmlSearchNs(node->doc, node, prefix);
xmlFree(prefix);
if (!ns)
{
xmlFree(local);
if (item) *item = NULL;
return item ? S_FALSE : E_INVALIDARG;
}
uriW = bstr_from_xmlChar(ns->href);
localW = bstr_from_xmlChar(local);
xmlFree(local);
TRACE("got qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
hr = domelem_get_qualified_item(node, localW, uriW, item);
SysFreeString(localW);
SysFreeString(uriW);
return hr;
}
static HRESULT domelem_set_named_item(xmlNodePtr node, IXMLDOMNode *newItem, IXMLDOMNode **namedItem)
{
xmlNodePtr nodeNew;
xmlnode *ThisNew;
TRACE("(%p)->(%p %p)\n", node, newItem, namedItem );
if(!newItem)
return E_INVALIDARG;
if(namedItem) *namedItem = NULL;
/* Must be an Attribute */
ThisNew = get_node_obj( newItem );
if(!ThisNew) return E_FAIL;
if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
return E_FAIL;
if(!ThisNew->node->parent)
if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
nodeNew = xmlAddChild(node, ThisNew->node);
if(namedItem)
*namedItem = create_node( nodeNew );
return S_OK;
}
static HRESULT domelem_remove_qualified_item(xmlNodePtr node, BSTR name, BSTR uri, IXMLDOMNode **item)
{
xmlChar *nameA, *href;
xmlAttrPtr attr;
TRACE("(%p)->(%s %s %p)\n", node, debugstr_w(name), debugstr_w(uri), item);
if (!name) return E_INVALIDARG;
if (uri && *uri)
{
href = xmlchar_from_wchar(uri);
if (!href) return E_OUTOFMEMORY;
}
else
href = NULL;
nameA = xmlchar_from_wchar(name);
if (!nameA)
{
heap_free(href);
return E_OUTOFMEMORY;
}
attr = xmlHasNsProp(node, nameA, href);
heap_free(nameA);
heap_free(href);
if (!attr)
{
if (item) *item = NULL;
return S_FALSE;
}
if (item)
{
xmlUnlinkNode( (xmlNodePtr) attr );
xmldoc_add_orphan( attr->doc, (xmlNodePtr) attr );
*item = create_node( (xmlNodePtr) attr );
}
else
{
if (xmlRemoveProp(attr) == -1)
ERR("xmlRemoveProp failed\n");
}
return S_OK;
}
static HRESULT domelem_remove_named_item(xmlNodePtr node, BSTR name, IXMLDOMNode **item)
{
TRACE("(%p)->(%s %p)\n", node, debugstr_w(name), item);
return domelem_remove_qualified_item(node, name, NULL, item);
}
static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode **item)
{
xmlAttrPtr curr;
LONG attrIndex;
TRACE("(%p)->(%d %p)\n", node, index, item);
*item = NULL;
if (index < 0)
return S_FALSE;
curr = node->properties;
for (attrIndex = 0; attrIndex < index; attrIndex++) {
if (curr->next == NULL)
return S_FALSE;
else
curr = curr->next;
}
*item = create_node( (xmlNodePtr) curr );
return S_OK;
}
static HRESULT domelem_get_length(const xmlNodePtr node, LONG *length)
{
xmlAttrPtr first;
xmlAttrPtr curr;
LONG attrCount;
TRACE("(%p)->(%p)\n", node, length);
if( !length )
return E_INVALIDARG;
first = node->properties;
if (first == NULL) {
*length = 0;
return S_OK;
}
curr = first;
attrCount = 1;
while (curr->next) {
attrCount++;
curr = curr->next;
}
*length = attrCount;
return S_OK;
}
static HRESULT domelem_next_node(const xmlNodePtr node, LONG *iter, IXMLDOMNode **nextNode)
{
xmlAttrPtr curr;
LONG i;
TRACE("(%p)->(%d: %p)\n", node, *iter, nextNode);
*nextNode = NULL;
curr = node->properties;
for (i = 0; i < *iter; i++) {
if (curr->next == NULL)
return S_FALSE;
else
curr = curr->next;
}
(*iter)++;
*nextNode = create_node((xmlNodePtr)curr);
return S_OK;
}
static const struct nodemap_funcs domelem_attr_map = {
domelem_get_named_item,
domelem_set_named_item,
domelem_remove_named_item,
domelem_get_item,
domelem_get_length,
domelem_get_qualified_item,
domelem_remove_qualified_item,
domelem_next_node
};
static const tid_t domelem_iface_tids[] = {
IXMLDOMElement_tid,
0
......
......@@ -228,6 +228,28 @@ static inline xmlNodePtr wine_xmlFirstElementChild(xmlNodePtr parent)
#define xmlFirstElementChild wine_xmlFirstElementChild
#endif
/* IXMLDOMNode Internal Structure */
typedef struct _xmlnode
{
DispatchEx dispex;
IXMLDOMNode *iface;
IXMLDOMNode *parent;
xmlNodePtr node;
} xmlnode;
/* IXMLDOMNamedNodeMap custom function table */
struct nodemap_funcs
{
HRESULT (*get_named_item)(const xmlNodePtr,BSTR,IXMLDOMNode**);
HRESULT (*set_named_item)(xmlNodePtr,IXMLDOMNode*,IXMLDOMNode**);
HRESULT (*remove_named_item)(xmlNodePtr,BSTR,IXMLDOMNode**);
HRESULT (*get_item)(xmlNodePtr,LONG,IXMLDOMNode**);
HRESULT (*get_length)(xmlNodePtr,LONG*);
HRESULT (*get_qualified_item)(const xmlNodePtr,BSTR,BSTR,IXMLDOMNode**);
HRESULT (*remove_qualified_item)(xmlNodePtr,BSTR,BSTR,IXMLDOMNode**);
HRESULT (*next_node)(const xmlNodePtr,LONG*,IXMLDOMNode**);
};
/* constructors */
extern IUnknown *create_domdoc( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IUnknown *create_xmldoc( void ) DECLSPEC_HIDDEN;
......@@ -239,7 +261,7 @@ extern IUnknown *create_pi( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IUnknown *create_comment( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IUnknown *create_cdata( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IXMLDOMNodeList *create_children_nodelist( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr ) DECLSPEC_HIDDEN;
extern IXMLDOMNamedNodeMap *create_nodemap( xmlNodePtr, const struct nodemap_funcs* ) DECLSPEC_HIDDEN;
extern IUnknown *create_doc_Implementation(void) DECLSPEC_HIDDEN;
extern IUnknown *create_doc_fragment( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IUnknown *create_doc_entity_ref( xmlNodePtr ) DECLSPEC_HIDDEN;
......@@ -282,15 +304,6 @@ extern BOOL is_preserving_whitespace(xmlNodePtr node) DECLSPEC_HIDDEN;
extern BOOL is_xpathmode(const xmlDocPtr doc) DECLSPEC_HIDDEN;
extern void set_xpathmode(xmlDocPtr doc, BOOL xpath) DECLSPEC_HIDDEN;
/* IXMLDOMNode Internal Structure */
typedef struct _xmlnode
{
DispatchEx dispex;
IXMLDOMNode *iface;
IXMLDOMNode *parent;
xmlNodePtr node;
} xmlnode;
extern void init_xmlnode(xmlnode*,xmlNodePtr,IXMLDOMNode*,dispex_static_data_t*) DECLSPEC_HIDDEN;
extern void destroy_xmlnode(xmlnode*) DECLSPEC_HIDDEN;
extern BOOL node_query_interface(xmlnode*,REFIID,void**) DECLSPEC_HIDDEN;
......
......@@ -53,6 +53,8 @@ typedef struct _xmlnodemap
xmlNodePtr node;
LONG iterator;
const struct nodemap_funcs *funcs;
} xmlnodemap;
static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface )
......@@ -202,44 +204,10 @@ static HRESULT WINAPI xmlnodemap_getNamedItem(
IXMLDOMNode** item)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlChar *nameA, *local, *prefix;
BSTR uriW, localW;
xmlNsPtr ns;
HRESULT hr;
TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), item );
nameA = xmlchar_from_wchar(name);
local = xmlSplitQName2(nameA, &prefix);
heap_free(nameA);
if (!local)
return IXMLDOMNamedNodeMap_getQualifiedItem(iface, name, NULL, item);
/* try to get namespace uri for supplied qualified name */
ns = xmlSearchNs(This->node->doc, This->node, prefix);
xmlFree(prefix);
if (!ns)
{
xmlFree(local);
if (item) *item = NULL;
return item ? S_FALSE : E_INVALIDARG;
}
uriW = bstr_from_xmlChar(ns->href);
localW = bstr_from_xmlChar(local);
xmlFree(local);
TRACE("got qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
hr = IXMLDOMNamedNodeMap_getQualifiedItem(iface, localW, uriW, item);
SysFreeString(localW);
SysFreeString(uriW);
return hr;
return This->funcs->get_named_item(This->node, name, item);
}
static HRESULT WINAPI xmlnodemap_setNamedItem(
......@@ -248,32 +216,10 @@ static HRESULT WINAPI xmlnodemap_setNamedItem(
IXMLDOMNode** namedItem)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlNodePtr nodeNew;
xmlnode *ThisNew;
TRACE("(%p)->(%p %p)\n", This, newItem, namedItem );
if(!newItem)
return E_INVALIDARG;
if(namedItem) *namedItem = NULL;
/* Must be an Attribute */
ThisNew = get_node_obj( newItem );
if(!ThisNew) return E_FAIL;
if(ThisNew->node->type != XML_ATTRIBUTE_NODE)
return E_FAIL;
if(!ThisNew->node->parent)
if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
nodeNew = xmlAddChild(This->node, ThisNew->node);
if(namedItem)
*namedItem = create_node( nodeNew );
return S_OK;
return This->funcs->set_named_item(This->node, newItem, namedItem);
}
static HRESULT WINAPI xmlnodemap_removeNamedItem(
......@@ -282,172 +228,59 @@ static HRESULT WINAPI xmlnodemap_removeNamedItem(
IXMLDOMNode** namedItem)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), namedItem );
return IXMLDOMNamedNodeMap_removeQualifiedItem(iface, name, NULL, namedItem);
return This->funcs->remove_named_item(This->node, name, namedItem);
}
static HRESULT WINAPI xmlnodemap_get_item(
IXMLDOMNamedNodeMap *iface,
LONG index,
IXMLDOMNode** listItem)
IXMLDOMNode** item)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlAttrPtr curr;
LONG attrIndex;
TRACE("(%p)->(%d %p)\n", This, index, listItem);
*listItem = NULL;
TRACE("(%p)->(%d %p)\n", This, index, item);
if (index < 0)
return S_FALSE;
curr = This->node->properties;
for (attrIndex = 0; attrIndex < index; attrIndex++) {
if (curr->next == NULL)
return S_FALSE;
else
curr = curr->next;
}
*listItem = create_node( (xmlNodePtr) curr );
return S_OK;
return This->funcs->get_item(This->node, index, item);
}
static HRESULT WINAPI xmlnodemap_get_length(
IXMLDOMNamedNodeMap *iface,
LONG *listLength)
LONG *length)
{
xmlAttrPtr first;
xmlAttrPtr curr;
LONG attrCount;
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
TRACE("(%p)->(%p)\n", This, listLength);
if( !listLength )
return E_INVALIDARG;
first = This->node->properties;
if (first == NULL) {
*listLength = 0;
return S_OK;
}
TRACE("(%p)->(%p)\n", This, length);
curr = first;
attrCount = 1;
while (curr->next) {
attrCount++;
curr = curr->next;
}
*listLength = attrCount;
return S_OK;
return This->funcs->get_length(This->node, length);
}
static HRESULT WINAPI xmlnodemap_getQualifiedItem(
IXMLDOMNamedNodeMap *iface,
BSTR baseName,
BSTR namespaceURI,
IXMLDOMNode** qualifiedItem)
IXMLDOMNode** item)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlAttrPtr attr;
xmlChar *href;
xmlChar *name;
TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), qualifiedItem);
if (!baseName || !qualifiedItem) return E_INVALIDARG;
if (namespaceURI && *namespaceURI)
{
href = xmlchar_from_wchar(namespaceURI);
if (!href) return E_OUTOFMEMORY;
}
else
href = NULL;
name = xmlchar_from_wchar(baseName);
if (!name)
{
heap_free(href);
return E_OUTOFMEMORY;
}
attr = xmlHasNsProp(This->node, name, href);
heap_free(name);
heap_free(href);
if (!attr)
{
*qualifiedItem = NULL;
return S_FALSE;
}
TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), item);
*qualifiedItem = create_node((xmlNodePtr)attr);
return S_OK;
return This->funcs->get_qualified_item(This->node, baseName, namespaceURI, item);
}
static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
IXMLDOMNamedNodeMap *iface,
BSTR baseName,
BSTR namespaceURI,
IXMLDOMNode** qualifiedItem)
IXMLDOMNode** item)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlAttrPtr attr;
xmlChar *name;
xmlChar *href;
TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), qualifiedItem);
if (!baseName) return E_INVALIDARG;
if (namespaceURI && *namespaceURI)
{
href = xmlchar_from_wchar(namespaceURI);
if (!href) return E_OUTOFMEMORY;
}
else
href = NULL;
ERR("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), item);
name = xmlchar_from_wchar(baseName);
if (!name)
{
heap_free(href);
return E_OUTOFMEMORY;
}
attr = xmlHasNsProp( This->node, name, href );
heap_free(name);
heap_free(href);
if ( !attr )
{
if (qualifiedItem) *qualifiedItem = NULL;
return S_FALSE;
}
if ( qualifiedItem )
{
xmlUnlinkNode( (xmlNodePtr) attr );
xmldoc_add_orphan( attr->doc, (xmlNodePtr) attr );
*qualifiedItem = create_node( (xmlNodePtr) attr );
}
else
{
if (xmlRemoveProp(attr) == -1)
ERR("xmlRemoveProp failed\n");
}
return S_OK;
return This->funcs->remove_qualified_item(This->node, baseName, namespaceURI, item);
}
static HRESULT WINAPI xmlnodemap_nextNode(
......@@ -455,27 +288,10 @@ static HRESULT WINAPI xmlnodemap_nextNode(
IXMLDOMNode** nextItem)
{
xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
xmlAttrPtr curr;
LONG attrIndex;
TRACE("(%p)->(%p: %d)\n", This, nextItem, This->iterator);
*nextItem = NULL;
curr = This->node->properties;
for (attrIndex = 0; attrIndex < This->iterator; attrIndex++) {
if (curr->next == NULL)
return S_FALSE;
else
curr = curr->next;
}
This->iterator++;
*nextItem = create_node( (xmlNodePtr) curr );
return S_OK;
return This->funcs->next_node(This->node, &This->iterator, nextItem);
}
static HRESULT WINAPI xmlnodemap_reset(
......@@ -626,7 +442,7 @@ static dispex_static_data_t xmlnodemap_dispex = {
xmlnodemap_iface_tids
};
IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr node )
IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs *funcs)
{
xmlnodemap *This;
......@@ -639,6 +455,7 @@ IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr node )
This->node = node;
This->ref = 1;
This->iterator = 0;
This->funcs = funcs;
init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
......
......@@ -49,6 +49,8 @@ typedef struct _dom_pi
LONG ref;
} dom_pi;
static const struct nodemap_funcs dom_pi_attr_map;
static inline dom_pi *impl_from_IXMLDOMProcessingInstruction( IXMLDOMProcessingInstruction *iface )
{
return CONTAINING_RECORD(iface, dom_pi, IXMLDOMProcessingInstruction_iface);
......@@ -128,13 +130,10 @@ static HRESULT WINAPI dom_pi_GetTypeInfo(
ITypeInfo** ppTInfo )
{
dom_pi *This = impl_from_IXMLDOMProcessingInstruction( iface );
HRESULT hr;
TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
hr = get_typeinfo(IXMLDOMProcessingInstruction_tid, ppTInfo);
return hr;
return get_typeinfo(IXMLDOMProcessingInstruction_tid, ppTInfo);
}
static HRESULT WINAPI dom_pi_GetIDsOfNames(
......@@ -334,7 +333,7 @@ static HRESULT WINAPI dom_pi_get_attributes(
if (!strcmpW(name, xmlW))
{
FIXME("created dummy map for <?xml ?>\n");
*map = create_nodemap(This->node.node);
*map = create_nodemap(This->node.node, &dom_pi_attr_map);
SysFreeString(name);
return S_OK;
}
......@@ -705,6 +704,68 @@ static const struct IXMLDOMProcessingInstructionVtbl dom_pi_vtbl =
dom_pi_put_data
};
static HRESULT dom_pi_get_qualified_item(const xmlNodePtr node, BSTR name, BSTR uri,
IXMLDOMNode **item)
{
FIXME("(%p)->(%s %s %p): stub\n", node, debugstr_w(name), debugstr_w(uri), item);
return E_NOTIMPL;
}
static HRESULT dom_pi_get_named_item(const xmlNodePtr node, BSTR name, IXMLDOMNode **item)
{
FIXME("(%p)->(%s %p): stub\n", node, debugstr_w(name), item );
return E_NOTIMPL;
}
static HRESULT dom_pi_set_named_item(xmlNodePtr node, IXMLDOMNode *newItem, IXMLDOMNode **namedItem)
{
FIXME("(%p)->(%p %p): stub\n", node, newItem, namedItem );
return E_NOTIMPL;
}
static HRESULT dom_pi_remove_qualified_item(xmlNodePtr node, BSTR name, BSTR uri, IXMLDOMNode **item)
{
FIXME("(%p)->(%s %s %p): stub\n", node, debugstr_w(name), debugstr_w(uri), item);
return E_NOTIMPL;
}
static HRESULT dom_pi_remove_named_item(xmlNodePtr node, BSTR name, IXMLDOMNode **item)
{
FIXME("(%p)->(%s %p): stub\n", node, debugstr_w(name), item);
return E_NOTIMPL;
}
static HRESULT dom_pi_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode **item)
{
FIXME("(%p)->(%d %p): stub\n", node, index, item);
return E_NOTIMPL;
}
static HRESULT dom_pi_get_length(const xmlNodePtr node, LONG *length)
{
FIXME("(%p)->(%p): stub\n", node, length);
*length = 0;
return S_OK;
}
static HRESULT dom_pi_next_node(const xmlNodePtr node, LONG *iter, IXMLDOMNode **nextNode)
{
FIXME("(%p)->(%d %p): stub\n", node, *iter, nextNode);
return E_NOTIMPL;
}
static const struct nodemap_funcs dom_pi_attr_map = {
dom_pi_get_named_item,
dom_pi_set_named_item,
dom_pi_remove_named_item,
dom_pi_get_item,
dom_pi_get_length,
dom_pi_get_qualified_item,
dom_pi_remove_qualified_item,
dom_pi_next_node
};
static const tid_t dompi_iface_tids[] = {
IXMLDOMProcessingInstruction_tid,
0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment