msxml: Implement getElementsByTagName.
This commit is contained in:
parent
964ef89f09
commit
1c3daceb00
|
@ -656,8 +656,16 @@ static HRESULT WINAPI domdoc_getElementsByTagName(
|
||||||
BSTR tagName,
|
BSTR tagName,
|
||||||
IXMLDOMNodeList** resultList )
|
IXMLDOMNodeList** resultList )
|
||||||
{
|
{
|
||||||
FIXME("\n");
|
domdoc *This = impl_from_IXMLDOMDocument( iface );
|
||||||
return E_NOTIMPL;
|
xmlChar *name;
|
||||||
|
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(tagName), resultList);
|
||||||
|
|
||||||
|
name = xmlChar_from_wchar((WCHAR*)tagName);
|
||||||
|
*resultList = create_filtered_nodelist((xmlNodePtr)get_doc(This), name, TRUE);
|
||||||
|
HeapFree(GetProcessHeap(), 0, name);
|
||||||
|
|
||||||
|
if(!*resultList) return S_FALSE;
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DOMNodeType get_node_type(VARIANT Type)
|
static DOMNodeType get_node_type(VARIANT Type)
|
||||||
|
|
|
@ -37,7 +37,7 @@ extern IUnknown *create_element( xmlNodePtr element );
|
||||||
extern IUnknown *create_text( xmlNodePtr text );
|
extern IUnknown *create_text( xmlNodePtr text );
|
||||||
extern IXMLDOMNodeList *create_nodelist( xmlNodePtr node );
|
extern IXMLDOMNodeList *create_nodelist( xmlNodePtr node );
|
||||||
extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node );
|
extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node );
|
||||||
extern IXMLDOMNodeList *create_filtered_nodelist( xmlNodePtr, const xmlChar * );
|
extern IXMLDOMNodeList *create_filtered_nodelist( xmlNodePtr, const xmlChar *, BOOL );
|
||||||
|
|
||||||
extern void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xmlnode );
|
extern void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xmlnode );
|
||||||
|
|
||||||
|
|
|
@ -314,11 +314,11 @@ static HRESULT WINAPI xmlnode_get_childNodes(
|
||||||
switch(This->node->type)
|
switch(This->node->type)
|
||||||
{
|
{
|
||||||
case XML_ELEMENT_NODE:
|
case XML_ELEMENT_NODE:
|
||||||
*childList = create_filtered_nodelist( This->node->children, (const xmlChar *)"*" );
|
*childList = create_filtered_nodelist( This->node->children, (const xmlChar *)"*", FALSE );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XML_ATTRIBUTE_NODE:
|
case XML_ATTRIBUTE_NODE:
|
||||||
*childList = create_filtered_nodelist( This->node->children, (const xmlChar *)"node()" );
|
*childList = create_filtered_nodelist( This->node->children, (const xmlChar *)"node()", FALSE );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -620,7 +620,7 @@ static HRESULT WINAPI xmlnode_selectNodes(
|
||||||
if( !This->node->children )
|
if( !This->node->children )
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
*resultList = create_filtered_nodelist( This->node->children, str );
|
*resultList = create_filtered_nodelist( This->node->children, str, FALSE );
|
||||||
HeapFree( GetProcessHeap(), 0, str );
|
HeapFree( GetProcessHeap(), 0, str );
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct xslt_info {
|
||||||
xsltStylesheetPtr sheet;
|
xsltStylesheetPtr sheet;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void xlst_info_init( struct xslt_info *info )
|
static void xslt_info_init( struct xslt_info *info )
|
||||||
{
|
{
|
||||||
info->ctxt = NULL;
|
info->ctxt = NULL;
|
||||||
info->pattern = NULL;
|
info->pattern = NULL;
|
||||||
|
@ -86,7 +86,10 @@ void free_xslt_info( struct xslt_info *info )
|
||||||
xsltFreeTransformContext( info->ctxt );
|
xsltFreeTransformContext( info->ctxt );
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT xslt_next_match( struct xslt_info *info, xmlNodePtr *node )
|
|
||||||
|
static xmlNodePtr get_next_node( struct xslt_info *info, xmlNodePtr node, xmlNodePtr *top_level_node );
|
||||||
|
|
||||||
|
static HRESULT xslt_next_match( struct xslt_info *info, xmlNodePtr *node, xmlNodePtr *top_level_node )
|
||||||
{
|
{
|
||||||
if (!info->ctxt)
|
if (!info->ctxt)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
@ -107,7 +110,7 @@ static HRESULT xslt_next_match( struct xslt_info *info, xmlNodePtr *node )
|
||||||
ERR("Pattern match failed\n");
|
ERR("Pattern match failed\n");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
*node = (*node)->next;
|
*node = get_next_node(info, *node, top_level_node);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +121,7 @@ struct xslt_info {
|
||||||
/* empty */
|
/* empty */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void xlst_info_init( struct xslt_info *info )
|
static void xslt_info_init( struct xslt_info *info )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,19 +135,42 @@ static int create_xslt_parser( struct xslt_info *info, xmlNodePtr node, const xm
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT xslt_next_match( struct xslt_info *info, xmlNodePtr *node )
|
static HRESULT xslt_next_match( struct xslt_info *info, xmlNodePtr *node, xmlNodePtr *top_level_node )
|
||||||
{
|
{
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static xmlNodePtr get_next_node( struct xslt_info *info, xmlNodePtr node, xmlNodePtr *top_level_node )
|
||||||
|
{
|
||||||
|
if(!top_level_node) return node->next;
|
||||||
|
|
||||||
|
if(node->children) return node->children;
|
||||||
|
if(node->next)
|
||||||
|
{
|
||||||
|
if(node == *top_level_node)
|
||||||
|
*top_level_node = node->next;
|
||||||
|
return node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node != *top_level_node && node->parent)
|
||||||
|
{
|
||||||
|
if(node->parent == *top_level_node)
|
||||||
|
*top_level_node = node->parent->next;
|
||||||
|
return node->parent->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _xmlnodelist
|
typedef struct _xmlnodelist
|
||||||
{
|
{
|
||||||
const struct IXMLDOMNodeListVtbl *lpVtbl;
|
const struct IXMLDOMNodeListVtbl *lpVtbl;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
xmlNodePtr node;
|
xmlNodePtr node;
|
||||||
xmlNodePtr current;
|
xmlNodePtr current;
|
||||||
|
xmlNodePtr top_level_node;
|
||||||
|
BOOL enum_children;
|
||||||
struct xslt_info xinfo;
|
struct xslt_info xinfo;
|
||||||
} xmlnodelist;
|
} xmlnodelist;
|
||||||
|
|
||||||
|
@ -252,7 +278,8 @@ static HRESULT WINAPI xmlnodelist_get_item(
|
||||||
IXMLDOMNode** listItem)
|
IXMLDOMNode** listItem)
|
||||||
{
|
{
|
||||||
xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
|
xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
|
||||||
xmlNodePtr curr;
|
xmlNodePtr curr, tmp;
|
||||||
|
xmlNodePtr *top_level_node = NULL;
|
||||||
long nodeIndex = 0;
|
long nodeIndex = 0;
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
|
|
||||||
|
@ -265,12 +292,18 @@ static HRESULT WINAPI xmlnodelist_get_item(
|
||||||
|
|
||||||
curr = This->node;
|
curr = This->node;
|
||||||
|
|
||||||
|
if(This->enum_children)
|
||||||
|
{
|
||||||
|
tmp = curr;
|
||||||
|
top_level_node = &tmp;
|
||||||
|
}
|
||||||
|
|
||||||
while(curr)
|
while(curr)
|
||||||
{
|
{
|
||||||
r = xslt_next_match( &This->xinfo, &curr );
|
r = xslt_next_match( &This->xinfo, &curr, top_level_node);
|
||||||
if(FAILED(r) || !curr) return S_FALSE;
|
if(FAILED(r) || !curr) return S_FALSE;
|
||||||
if(nodeIndex++ == index) break;
|
if(nodeIndex++ == index) break;
|
||||||
curr = curr->next;
|
curr = get_next_node(&This->xinfo, curr, top_level_node);
|
||||||
}
|
}
|
||||||
if(!curr) return S_FALSE;
|
if(!curr) return S_FALSE;
|
||||||
|
|
||||||
|
@ -284,7 +317,8 @@ static HRESULT WINAPI xmlnodelist_get_length(
|
||||||
long* listLength)
|
long* listLength)
|
||||||
{
|
{
|
||||||
|
|
||||||
xmlNodePtr curr;
|
xmlNodePtr curr, tmp;
|
||||||
|
xmlNodePtr *top_level_node = NULL;
|
||||||
long nodeCount = 0;
|
long nodeCount = 0;
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
|
|
||||||
|
@ -297,9 +331,15 @@ static HRESULT WINAPI xmlnodelist_get_length(
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(curr = This->node; curr; curr = curr->next)
|
if(This->enum_children)
|
||||||
{
|
{
|
||||||
r = xslt_next_match( &This->xinfo, &curr );
|
tmp = curr;
|
||||||
|
top_level_node = &tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(curr = This->node; curr; curr = get_next_node(&This->xinfo, curr, top_level_node))
|
||||||
|
{
|
||||||
|
r = xslt_next_match( &This->xinfo, &curr, top_level_node );
|
||||||
if(FAILED(r) || !curr) break;
|
if(FAILED(r) || !curr) break;
|
||||||
nodeCount++;
|
nodeCount++;
|
||||||
}
|
}
|
||||||
|
@ -314,10 +354,14 @@ static HRESULT WINAPI xmlnodelist_nextNode(
|
||||||
{
|
{
|
||||||
xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
|
xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
|
xmlNodePtr *top_level_node = NULL;
|
||||||
|
|
||||||
TRACE("%p %p\n", This, nextItem );
|
TRACE("%p %p\n", This, nextItem );
|
||||||
|
|
||||||
r = xslt_next_match( &This->xinfo, &This->current );
|
if(This->enum_children)
|
||||||
|
top_level_node = &This->top_level_node;
|
||||||
|
|
||||||
|
r = xslt_next_match( &This->xinfo, &This->current, top_level_node );
|
||||||
if (FAILED(r) )
|
if (FAILED(r) )
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -325,7 +369,7 @@ static HRESULT WINAPI xmlnodelist_nextNode(
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
*nextItem = create_node( This->current );
|
*nextItem = create_node( This->current );
|
||||||
This->current = This->current->next;
|
This->current = get_next_node(&This->xinfo, This->current, top_level_node);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,8 +419,10 @@ static xmlnodelist *new_nodelist( xmlNodePtr node )
|
||||||
nodelist->lpVtbl = &xmlnodelist_vtbl;
|
nodelist->lpVtbl = &xmlnodelist_vtbl;
|
||||||
nodelist->ref = 1;
|
nodelist->ref = 1;
|
||||||
nodelist->node = node;
|
nodelist->node = node;
|
||||||
nodelist->current = node;
|
nodelist->current = node;
|
||||||
xlst_info_init( &nodelist->xinfo );
|
nodelist->top_level_node = node;
|
||||||
|
nodelist->enum_children = FALSE;
|
||||||
|
xslt_info_init( &nodelist->xinfo );
|
||||||
|
|
||||||
xmldoc_add_ref( node->doc );
|
xmldoc_add_ref( node->doc );
|
||||||
|
|
||||||
|
@ -391,12 +437,15 @@ IXMLDOMNodeList* create_nodelist( xmlNodePtr node )
|
||||||
return (IXMLDOMNodeList*) &nodelist->lpVtbl;
|
return (IXMLDOMNodeList*) &nodelist->lpVtbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
IXMLDOMNodeList* create_filtered_nodelist( xmlNodePtr node, const xmlChar *str )
|
IXMLDOMNodeList* create_filtered_nodelist( xmlNodePtr node, const xmlChar *str, BOOL enum_children )
|
||||||
{
|
{
|
||||||
xmlnodelist *This = new_nodelist( node );
|
xmlnodelist *This = new_nodelist( node );
|
||||||
|
|
||||||
if (create_xslt_parser( &This->xinfo, node, str ))
|
if (create_xslt_parser( &This->xinfo, node, str ))
|
||||||
|
{
|
||||||
|
This->enum_children = enum_children;
|
||||||
return (IXMLDOMNodeList*) &This->lpVtbl;
|
return (IXMLDOMNodeList*) &This->lpVtbl;
|
||||||
|
}
|
||||||
|
|
||||||
IXMLDOMNodeList_Release( (IXMLDOMNodeList*) &This->lpVtbl );
|
IXMLDOMNodeList_Release( (IXMLDOMNodeList*) &This->lpVtbl );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -73,6 +73,7 @@ static const WCHAR szlc[] = { 'l','c',0 };
|
||||||
static const WCHAR szbs[] = { 'b','s',0 };
|
static const WCHAR szbs[] = { 'b','s',0 };
|
||||||
static const WCHAR szstr1[] = { 's','t','r','1',0 };
|
static const WCHAR szstr1[] = { 's','t','r','1',0 };
|
||||||
static const WCHAR szstr2[] = { 's','t','r','2',0 };
|
static const WCHAR szstr2[] = { 's','t','r','2',0 };
|
||||||
|
static const WCHAR szstar[] = { '*',0 };
|
||||||
|
|
||||||
void test_domdoc( void )
|
void test_domdoc( void )
|
||||||
{
|
{
|
||||||
|
@ -775,6 +776,64 @@ static void test_create(void)
|
||||||
IXMLDOMDocument_Release( doc );
|
IXMLDOMDocument_Release( doc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_getElementsByTagName(void)
|
||||||
|
{
|
||||||
|
HRESULT r;
|
||||||
|
BSTR str;
|
||||||
|
VARIANT_BOOL b;
|
||||||
|
IXMLDOMDocument *doc;
|
||||||
|
IXMLDOMNodeList *node_list;
|
||||||
|
LONG len;
|
||||||
|
|
||||||
|
r = CoCreateInstance( &CLSID_DOMDocument, NULL,
|
||||||
|
CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
|
||||||
|
if( r != S_OK )
|
||||||
|
return;
|
||||||
|
|
||||||
|
str = SysAllocString( szComplete4 );
|
||||||
|
r = IXMLDOMDocument_loadXML( doc, str, &b );
|
||||||
|
ok( r == S_OK, "loadXML failed\n");
|
||||||
|
ok( b == VARIANT_TRUE, "failed to load XML string\n");
|
||||||
|
SysFreeString( str );
|
||||||
|
|
||||||
|
str = SysAllocString( szstar );
|
||||||
|
r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
r = IXMLDOMNodeList_get_length( node_list, &len );
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
ok( len == 3, "len %ld\n", len );
|
||||||
|
IXMLDOMNodeList_Release( node_list );
|
||||||
|
SysFreeString( str );
|
||||||
|
|
||||||
|
str = SysAllocString( szbs );
|
||||||
|
r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
r = IXMLDOMNodeList_get_length( node_list, &len );
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
ok( len == 1, "len %ld\n", len );
|
||||||
|
IXMLDOMNodeList_Release( node_list );
|
||||||
|
SysFreeString( str );
|
||||||
|
|
||||||
|
str = SysAllocString( szdl );
|
||||||
|
r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
r = IXMLDOMNodeList_get_length( node_list, &len );
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
ok( len == 0, "len %ld\n", len );
|
||||||
|
IXMLDOMNodeList_Release( node_list );
|
||||||
|
SysFreeString( str );
|
||||||
|
|
||||||
|
str = SysAllocString( szstr1 );
|
||||||
|
r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
r = IXMLDOMNodeList_get_length( node_list, &len );
|
||||||
|
ok( r == S_OK, "ret %08lx\n", r );
|
||||||
|
ok( len == 0, "len %ld\n", len );
|
||||||
|
IXMLDOMNodeList_Release( node_list );
|
||||||
|
SysFreeString( str );
|
||||||
|
|
||||||
|
IXMLDOMDocument_Release( doc );
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(domdoc)
|
START_TEST(domdoc)
|
||||||
{
|
{
|
||||||
|
@ -787,6 +846,7 @@ START_TEST(domdoc)
|
||||||
test_domnode();
|
test_domnode();
|
||||||
test_refs();
|
test_refs();
|
||||||
test_create();
|
test_create();
|
||||||
|
test_getElementsByTagName();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue