msxml: Implement getElementsByTagName.

This commit is contained in:
Huw Davies 2006-02-14 10:38:21 +01:00 committed by Alexandre Julliard
parent 964ef89f09
commit 1c3daceb00
5 changed files with 139 additions and 22 deletions

View File

@ -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)

View File

@ -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 );

View File

@ -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;
} }

View File

@ -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;

View File

@ -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();
} }