Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
e1cbec75
Commit
e1cbec75
authored
May 11, 2007
by
Mikołaj Zalewski
Committed by
Alexandre Julliard
May 18, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msxml3: Improve the XPath queries handling.
parent
ee33e405
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
584 additions
and
241 deletions
+584
-241
Makefile.in
dlls/msxml3/Makefile.in
+1
-0
domdoc.c
dlls/msxml3/domdoc.c
+9
-6
msxml_private.h
dlls/msxml3/msxml_private.h
+3
-2
node.c
dlls/msxml3/node.c
+5
-28
nodelist.c
dlls/msxml3/nodelist.c
+23
-204
queryresult.c
dlls/msxml3/queryresult.c
+292
-0
Makefile.in
dlls/msxml3/tests/Makefile.in
+1
-1
domdoc.c
dlls/msxml3/tests/domdoc.c
+250
-0
No files found.
dlls/msxml3/Makefile.in
View file @
e1cbec75
...
@@ -20,6 +20,7 @@ C_SRCS = \
...
@@ -20,6 +20,7 @@ C_SRCS = \
nodemap.c
\
nodemap.c
\
parseerror.c
\
parseerror.c
\
pi.c
\
pi.c
\
queryresult.c
\
regsvr.c
\
regsvr.c
\
schema.c
\
schema.c
\
text.c
\
text.c
\
...
...
dlls/msxml3/domdoc.c
View file @
e1cbec75
...
@@ -823,15 +823,18 @@ static HRESULT WINAPI domdoc_getElementsByTagName(
...
@@ -823,15 +823,18 @@ static HRESULT WINAPI domdoc_getElementsByTagName(
IXMLDOMNodeList
**
resultList
)
IXMLDOMNodeList
**
resultList
)
{
{
domdoc
*
This
=
impl_from_IXMLDOMDocument2
(
iface
);
domdoc
*
This
=
impl_from_IXMLDOMDocument2
(
iface
);
xmlChar
*
name
;
LPWSTR
szPattern
;
HRESULT
hr
;
TRACE
(
"(%p)->(%s, %p)
\n
"
,
This
,
debugstr_w
(
tagName
),
resultList
);
TRACE
(
"(%p)->(%s, %p)
\n
"
,
This
,
debugstr_w
(
tagName
),
resultList
);
name
=
xmlChar_from_wchar
((
WCHAR
*
)
tagName
);
szPattern
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WCHAR
)
*
(
2
+
lstrlenW
(
tagName
)
+
1
)
);
*
resultList
=
create_filtered_nodelist
((
xmlNodePtr
)
get_doc
(
This
),
name
,
TRUE
)
;
szPattern
[
0
]
=
szPattern
[
1
]
=
'/'
;
HeapFree
(
GetProcessHeap
(),
0
,
n
ame
);
lstrcpyW
(
szPattern
+
2
,
tagN
ame
);
if
(
!*
resultList
)
return
S_FALSE
;
hr
=
queryresult_create
((
xmlNodePtr
)
get_doc
(
This
),
szPattern
,
resultList
);
return
S_OK
;
HeapFree
(
GetProcessHeap
(),
0
,
szPattern
);
return
hr
;
}
}
static
DOMNodeType
get_node_type
(
VARIANT
Type
)
static
DOMNodeType
get_node_type
(
VARIANT
Type
)
...
...
dlls/msxml3/msxml_private.h
View file @
e1cbec75
...
@@ -41,9 +41,10 @@ extern IUnknown *create_attribute( xmlNodePtr attribute );
...
@@ -41,9 +41,10 @@ extern IUnknown *create_attribute( xmlNodePtr attribute );
extern
IUnknown
*
create_text
(
xmlNodePtr
text
);
extern
IUnknown
*
create_text
(
xmlNodePtr
text
);
extern
IUnknown
*
create_pi
(
xmlNodePtr
pi
);
extern
IUnknown
*
create_pi
(
xmlNodePtr
pi
);
extern
IUnknown
*
create_comment
(
xmlNodePtr
comment
);
extern
IUnknown
*
create_comment
(
xmlNodePtr
comment
);
extern
IXMLDOMNodeList
*
create_
nodelist
(
xmlNodePtr
node
);
extern
IXMLDOMNodeList
*
create_
children_nodelist
(
xmlNodePtr
);
extern
IXMLDOMNamedNodeMap
*
create_nodemap
(
IXMLDOMNode
*
node
);
extern
IXMLDOMNamedNodeMap
*
create_nodemap
(
IXMLDOMNode
*
node
);
extern
IXMLDOMNodeList
*
create_filtered_nodelist
(
xmlNodePtr
,
const
xmlChar
*
,
BOOL
);
extern
HRESULT
queryresult_create
(
xmlNodePtr
,
LPWSTR
,
IXMLDOMNodeList
**
);
extern
void
attach_xmlnode
(
IXMLDOMNode
*
node
,
xmlNodePtr
xmlnode
);
extern
void
attach_xmlnode
(
IXMLDOMNode
*
node
,
xmlNodePtr
xmlnode
);
...
...
dlls/msxml3/node.c
View file @
e1cbec75
...
@@ -311,23 +311,10 @@ static HRESULT WINAPI xmlnode_get_childNodes(
...
@@ -311,23 +311,10 @@ static HRESULT WINAPI xmlnode_get_childNodes(
if
(
!
childList
)
if
(
!
childList
)
return
E_INVALIDARG
;
return
E_INVALIDARG
;
switch
(
This
->
node
->
type
)
*
childList
=
create_children_nodelist
(
This
->
node
);
{
if
(
*
childList
==
NULL
)
case
XML_ELEMENT_NODE
:
return
E_OUTOFMEMORY
;
*
childList
=
create_filtered_nodelist
(
This
->
node
->
children
,
(
const
xmlChar
*
)
"*"
,
FALSE
);
break
;
case
XML_ATTRIBUTE_NODE
:
*
childList
=
create_filtered_nodelist
(
This
->
node
->
children
,
(
const
xmlChar
*
)
"node()"
,
FALSE
);
break
;
default:
FIXME
(
"unhandled node type %d
\n
"
,
This
->
node
->
type
);
break
;
}
if
(
!*
childList
)
return
S_FALSE
;
return
S_OK
;
return
S_OK
;
}
}
...
@@ -658,21 +645,10 @@ static HRESULT WINAPI xmlnode_selectNodes(
...
@@ -658,21 +645,10 @@ static HRESULT WINAPI xmlnode_selectNodes(
IXMLDOMNodeList
**
resultList
)
IXMLDOMNodeList
**
resultList
)
{
{
xmlnode
*
This
=
impl_from_IXMLDOMNode
(
iface
);
xmlnode
*
This
=
impl_from_IXMLDOMNode
(
iface
);
xmlChar
*
str
=
NULL
;
HRESULT
r
=
E_FAIL
;
TRACE
(
"%p %s %p
\n
"
,
This
,
debugstr_w
(
queryString
),
resultList
);
TRACE
(
"%p %s %p
\n
"
,
This
,
debugstr_w
(
queryString
),
resultList
);
str
=
xmlChar_from_wchar
(
queryString
);
return
queryresult_create
(
This
->
node
,
queryString
,
resultList
);
if
(
!
str
)
return
r
;
if
(
!
This
->
node
->
children
)
return
S_FALSE
;
*
resultList
=
create_filtered_nodelist
(
This
->
node
->
children
,
str
,
FALSE
);
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
S_OK
;
}
}
static
HRESULT
WINAPI
xmlnode_selectSingleNode
(
static
HRESULT
WINAPI
xmlnode_selectSingleNode
(
...
@@ -686,6 +662,7 @@ static HRESULT WINAPI xmlnode_selectSingleNode(
...
@@ -686,6 +662,7 @@ static HRESULT WINAPI xmlnode_selectSingleNode(
TRACE
(
"%p %s %p
\n
"
,
This
,
debugstr_w
(
queryString
),
resultNode
);
TRACE
(
"%p %s %p
\n
"
,
This
,
debugstr_w
(
queryString
),
resultNode
);
*
resultNode
=
NULL
;
r
=
IXMLDOMNode_selectNodes
(
iface
,
queryString
,
&
list
);
r
=
IXMLDOMNode_selectNodes
(
iface
,
queryString
,
&
list
);
if
(
r
==
S_OK
)
if
(
r
==
S_OK
)
{
{
...
...
dlls/msxml3/nodelist.c
View file @
e1cbec75
...
@@ -33,147 +33,25 @@
...
@@ -33,147 +33,25 @@
#include "wine/debug.h"
#include "wine/debug.h"
/* This file implements the object returned by childNodes property. Note that this is
* not the IXMLDOMNodeList returned by XPath querites - it's implemented in queryresult.c.
* They are different because the list returned by childNodes:
* - is "live" - changes to the XML tree are automatically reflected in the list
* - doesn't supports IXMLDOMSelection
* - note that an attribute node have a text child in DOM but not in the XPath data model
* thus the child is inaccessible by an XPath query
*/
WINE_DEFAULT_DEBUG_CHANNEL
(
msxml
);
WINE_DEFAULT_DEBUG_CHANNEL
(
msxml
);
#ifdef HAVE_LIBXML2
#ifdef HAVE_LIBXML2
#ifdef HAVE_LIBXSLT
#ifdef HAVE_LIBXSLT_PATTERN_H
#include <libxslt/pattern.h>
#endif
#ifdef HAVE_LIBXSLT_TRANSFORM_H
#include <libxslt/transform.h>
#endif
struct
xslt_info
{
xsltTransformContextPtr
ctxt
;
xsltCompMatchPtr
pattern
;
xsltStylesheetPtr
sheet
;
};
static
void
xslt_info_init
(
struct
xslt_info
*
info
)
{
info
->
ctxt
=
NULL
;
info
->
pattern
=
NULL
;
info
->
sheet
=
NULL
;
}
static
int
create_xslt_parser
(
struct
xslt_info
*
info
,
xmlNodePtr
node
,
const
xmlChar
*
str
)
{
if
(
!
node
)
return
1
;
info
->
sheet
=
xsltNewStylesheet
();
if
(
!
info
->
sheet
)
return
0
;
info
->
ctxt
=
xsltNewTransformContext
(
info
->
sheet
,
node
->
doc
);
if
(
!
info
->
ctxt
)
return
0
;
info
->
pattern
=
xsltCompilePattern
(
str
,
node
->
doc
,
node
,
info
->
sheet
,
info
->
ctxt
);
if
(
!
info
->
pattern
)
return
0
;
return
1
;
}
static
void
free_xslt_info
(
struct
xslt_info
*
info
)
{
if
(
info
->
pattern
)
xsltFreeCompMatchList
(
info
->
pattern
);
if
(
info
->
sheet
)
xsltFreeStylesheet
(
info
->
sheet
);
if
(
info
->
ctxt
)
xsltFreeTransformContext
(
info
->
ctxt
);
}
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
)
return
S_FALSE
;
/* make sure that the current element matches the pattern */
while
(
*
node
)
{
int
r
;
r
=
xsltTestCompMatchList
(
info
->
ctxt
,
*
node
,
info
->
pattern
);
if
(
1
==
r
)
{
TRACE
(
"Matched %p (%s)
\n
"
,
*
node
,
(
*
node
)
->
name
);
return
S_OK
;
}
if
(
r
!=
0
)
{
ERR
(
"Pattern match failed
\n
"
);
return
E_FAIL
;
}
*
node
=
get_next_node
(
info
,
*
node
,
top_level_node
);
}
return
S_OK
;
}
#else
struct
xslt_info
{
/* empty */
};
static
void
xslt_info_init
(
struct
xslt_info
*
info
)
{
}
void
free_xslt_info
(
struct
xslt_info
*
info
)
{
}
static
int
create_xslt_parser
(
struct
xslt_info
*
info
,
xmlNodePtr
node
,
const
xmlChar
*
str
)
{
MESSAGE
(
"libxslt was missing at compile time
\n
"
);
return
0
;
}
static
HRESULT
xslt_next_match
(
struct
xslt_info
*
info
,
xmlNodePtr
*
node
,
xmlNodePtr
*
top_level_node
)
{
return
S_FALSE
;
}
#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
parent
;
xmlNodePtr
current
;
xmlNodePtr
current
;
xmlNodePtr
top_level_node
;
BOOL
enum_children
;
struct
xslt_info
xinfo
;
}
xmlnodelist
;
}
xmlnodelist
;
static
inline
xmlnodelist
*
impl_from_IXMLDOMNodeList
(
IXMLDOMNodeList
*
iface
)
static
inline
xmlnodelist
*
impl_from_IXMLDOMNodeList
(
IXMLDOMNodeList
*
iface
)
...
@@ -222,8 +100,7 @@ static ULONG WINAPI xmlnodelist_Release(
...
@@ -222,8 +100,7 @@ static ULONG WINAPI xmlnodelist_Release(
ref
=
InterlockedDecrement
(
&
This
->
ref
);
ref
=
InterlockedDecrement
(
&
This
->
ref
);
if
(
ref
==
0
)
if
(
ref
==
0
)
{
{
free_xslt_info
(
&
This
->
xinfo
);
xmldoc_release
(
This
->
parent
->
doc
);
if
(
This
->
node
)
xmldoc_release
(
This
->
node
->
doc
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
}
...
@@ -281,10 +158,8 @@ static HRESULT WINAPI xmlnodelist_get_item(
...
@@ -281,10 +158,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
,
tmp
;
xmlNodePtr
curr
;
xmlNodePtr
*
top_level_node
=
NULL
;
long
nodeIndex
=
0
;
long
nodeIndex
=
0
;
HRESULT
r
;
TRACE
(
"%p %ld
\n
"
,
This
,
index
);
TRACE
(
"%p %ld
\n
"
,
This
,
index
);
...
@@ -293,20 +168,11 @@ static HRESULT WINAPI xmlnodelist_get_item(
...
@@ -293,20 +168,11 @@ static HRESULT WINAPI xmlnodelist_get_item(
if
(
index
<
0
)
if
(
index
<
0
)
return
S_FALSE
;
return
S_FALSE
;
curr
=
This
->
node
;
curr
=
This
->
parent
->
children
;
if
(
This
->
enum_children
)
{
tmp
=
curr
;
top_level_node
=
&
tmp
;
}
while
(
curr
)
while
(
curr
)
{
{
r
=
xslt_next_match
(
&
This
->
xinfo
,
&
curr
,
top_level_node
);
if
(
FAILED
(
r
)
||
!
curr
)
return
S_FALSE
;
if
(
nodeIndex
++
==
index
)
break
;
if
(
nodeIndex
++
==
index
)
break
;
curr
=
get_next_node
(
&
This
->
xinfo
,
curr
,
top_level_node
)
;
curr
=
curr
->
next
;
}
}
if
(
!
curr
)
return
S_FALSE
;
if
(
!
curr
)
return
S_FALSE
;
...
@@ -320,34 +186,18 @@ static HRESULT WINAPI xmlnodelist_get_length(
...
@@ -320,34 +186,18 @@ static HRESULT WINAPI xmlnodelist_get_length(
long
*
listLength
)
long
*
listLength
)
{
{
xmlNodePtr
curr
,
tmp
;
xmlNodePtr
curr
;
xmlNodePtr
*
top_level_node
=
NULL
;
long
nodeCount
=
0
;
long
nodeCount
=
0
;
HRESULT
r
;
xmlnodelist
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
xmlnodelist
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
TRACE
(
"%p
\n
"
,
This
);
TRACE
(
"%p
\n
"
,
This
);
if
(
This
->
node
==
NULL
)
{
curr
=
This
->
parent
->
children
;
*
listLength
=
0
;
return
S_OK
;
}
curr
=
This
->
node
;
if
(
This
->
enum_children
)
{
tmp
=
curr
;
top_level_node
=
&
tmp
;
}
while
(
curr
)
while
(
curr
)
{
{
r
=
xslt_next_match
(
&
This
->
xinfo
,
&
curr
,
top_level_node
);
if
(
FAILED
(
r
)
||
!
curr
)
break
;
nodeCount
++
;
nodeCount
++
;
curr
=
get_next_node
(
&
This
->
xinfo
,
curr
,
top_level_node
)
;
curr
=
curr
->
next
;
}
}
*
listLength
=
nodeCount
;
*
listLength
=
nodeCount
;
...
@@ -359,25 +209,16 @@ static HRESULT WINAPI xmlnodelist_nextNode(
...
@@ -359,25 +209,16 @@ static HRESULT WINAPI xmlnodelist_nextNode(
IXMLDOMNode
**
nextItem
)
IXMLDOMNode
**
nextItem
)
{
{
xmlnodelist
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
xmlnodelist
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
HRESULT
r
;
xmlNodePtr
*
top_level_node
=
NULL
;
TRACE
(
"%p %p
\n
"
,
This
,
nextItem
);
TRACE
(
"%p %p
\n
"
,
This
,
nextItem
);
*
nextItem
=
NULL
;
*
nextItem
=
NULL
;
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
)
)
return
r
;
if
(
!
This
->
current
)
if
(
!
This
->
current
)
return
S_FALSE
;
return
S_FALSE
;
*
nextItem
=
create_node
(
This
->
current
);
*
nextItem
=
create_node
(
This
->
current
);
This
->
current
=
get_next_node
(
&
This
->
xinfo
,
This
->
current
,
top_level_node
)
;
This
->
current
=
This
->
current
->
next
;
return
S_OK
;
return
S_OK
;
}
}
...
@@ -387,7 +228,7 @@ static HRESULT WINAPI xmlnodelist_reset(
...
@@ -387,7 +228,7 @@ static HRESULT WINAPI xmlnodelist_reset(
xmlnodelist
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
xmlnodelist
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
TRACE
(
"%p
\n
"
,
This
);
TRACE
(
"%p
\n
"
,
This
);
This
->
current
=
This
->
node
;
This
->
current
=
This
->
parent
->
children
;
return
S_OK
;
return
S_OK
;
}
}
...
@@ -416,7 +257,7 @@ static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
...
@@ -416,7 +257,7 @@ static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
xmlnodelist__newEnum
,
xmlnodelist__newEnum
,
};
};
static
xmlnodelist
*
new
_nodelist
(
xmlNodePtr
node
)
IXMLDOMNodeList
*
create_children
_nodelist
(
xmlNodePtr
node
)
{
{
xmlnodelist
*
nodelist
;
xmlnodelist
*
nodelist
;
...
@@ -426,34 +267,12 @@ static xmlnodelist *new_nodelist( xmlNodePtr node )
...
@@ -426,34 +267,12 @@ static xmlnodelist *new_nodelist( xmlNodePtr node )
nodelist
->
lpVtbl
=
&
xmlnodelist_vtbl
;
nodelist
->
lpVtbl
=
&
xmlnodelist_vtbl
;
nodelist
->
ref
=
1
;
nodelist
->
ref
=
1
;
nodelist
->
node
=
node
;
nodelist
->
parent
=
node
;
nodelist
->
current
=
node
;
nodelist
->
current
=
node
->
children
;
nodelist
->
top_level_node
=
node
;
nodelist
->
enum_children
=
FALSE
;
xslt_info_init
(
&
nodelist
->
xinfo
);
if
(
node
)
xmldoc_add_ref
(
node
->
doc
);
xmldoc_add_ref
(
node
->
doc
);
return
nodelist
;
}
IXMLDOMNodeList
*
create_nodelist
(
xmlNodePtr
node
)
{
xmlnodelist
*
nodelist
=
new_nodelist
(
node
);
return
(
IXMLDOMNodeList
*
)
&
nodelist
->
lpVtbl
;
return
(
IXMLDOMNodeList
*
)
&
nodelist
->
lpVtbl
;
}
}
IXMLDOMNodeList
*
create_filtered_nodelist
(
xmlNodePtr
node
,
const
xmlChar
*
str
,
BOOL
enum_children
)
{
xmlnodelist
*
This
=
new_nodelist
(
node
);
if
(
create_xslt_parser
(
&
This
->
xinfo
,
node
,
str
))
{
This
->
enum_children
=
enum_children
;
return
(
IXMLDOMNodeList
*
)
&
This
->
lpVtbl
;
}
IXMLDOMNodeList_Release
(
(
IXMLDOMNodeList
*
)
&
This
->
lpVtbl
);
return
NULL
;
}
#endif
#endif
dlls/msxml3/queryresult.c
0 → 100644
View file @
e1cbec75
/*
* XPath query result node list implementation (TODO: XSLPattern support)
*
* Copyright 2005 Mike McCormack
* Copyright 2007 Mikolaj Zalewski
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "config.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "msxml2.h"
#include "msxml_private.h"
#include "wine/debug.h"
/* This file implements the object returned by a XPath query. Note that this is
* not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
* They are different because the list returned by XPath queries:
* - is static - gives the results for the XML tree as it existed during the
* execution of the query
* - supports IXMLDOMSelection (TODO)
*
* TODO: XSLPattern support
*/
WINE_DEFAULT_DEBUG_CHANNEL
(
msxml
);
#ifdef HAVE_LIBXML2
#include <libxml/xpath.h>
static
const
struct
IXMLDOMNodeListVtbl
queryresult_vtbl
;
typedef
struct
_queryresult
{
const
struct
IXMLDOMNodeListVtbl
*
lpVtbl
;
LONG
ref
;
xmlNodePtr
node
;
xmlXPathObjectPtr
result
;
int
resultPos
;
}
queryresult
;
static
inline
queryresult
*
impl_from_IXMLDOMNodeList
(
IXMLDOMNodeList
*
iface
)
{
return
(
queryresult
*
)((
char
*
)
iface
-
FIELD_OFFSET
(
queryresult
,
lpVtbl
));
}
HRESULT
queryresult_create
(
xmlNodePtr
node
,
LPWSTR
szQuery
,
IXMLDOMNodeList
**
out
)
{
queryresult
*
This
=
CoTaskMemAlloc
(
sizeof
(
queryresult
));
xmlXPathContextPtr
ctxt
=
xmlXPathNewContext
(
node
->
doc
);
xmlChar
*
str
=
xmlChar_from_wchar
(
szQuery
);
HRESULT
hr
;
TRACE
(
"(%p, %s, %p)
\n
"
,
node
,
wine_dbgstr_w
(
szQuery
),
out
);
*
out
=
NULL
;
if
(
This
==
NULL
||
ctxt
==
NULL
||
str
==
NULL
)
{
hr
=
E_OUTOFMEMORY
;
goto
cleanup
;
}
This
->
lpVtbl
=
&
queryresult_vtbl
;
This
->
ref
=
1
;
This
->
resultPos
=
0
;
This
->
node
=
node
;
xmldoc_add_ref
(
This
->
node
->
doc
);
ctxt
->
node
=
node
;
This
->
result
=
xmlXPathEval
(
str
,
ctxt
);
if
(
!
This
->
result
||
This
->
result
->
type
!=
XPATH_NODESET
)
{
hr
=
E_FAIL
;
goto
cleanup
;
}
*
out
=
(
IXMLDOMNodeList
*
)
This
;
hr
=
S_OK
;
TRACE
(
"found %d matches
\n
"
,
This
->
result
->
nodesetval
->
nodeNr
);
cleanup:
if
(
This
!=
NULL
&&
FAILED
(
hr
))
IXMLDOMNodeList_Release
(
(
IXMLDOMNodeList
*
)
&
This
->
lpVtbl
);
if
(
ctxt
!=
NULL
)
xmlXPathFreeContext
(
ctxt
);
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
hr
;
}
static
HRESULT
WINAPI
queryresult_QueryInterface
(
IXMLDOMNodeList
*
iface
,
REFIID
riid
,
void
**
ppvObject
)
{
TRACE
(
"%p %s %p
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppvObject
);
if
(
IsEqualGUID
(
riid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
riid
,
&
IID_IDispatch
)
||
IsEqualGUID
(
riid
,
&
IID_IXMLDOMNodeList
)
)
{
*
ppvObject
=
iface
;
}
else
{
FIXME
(
"interface %s not implemented
\n
"
,
debugstr_guid
(
riid
));
*
ppvObject
=
NULL
;
return
E_NOINTERFACE
;
}
IXMLDOMNodeList_AddRef
(
iface
);
return
S_OK
;
}
static
ULONG
WINAPI
queryresult_AddRef
(
IXMLDOMNodeList
*
iface
)
{
queryresult
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
return
InterlockedIncrement
(
&
This
->
ref
);
}
static
ULONG
WINAPI
queryresult_Release
(
IXMLDOMNodeList
*
iface
)
{
queryresult
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
ULONG
ref
;
ref
=
InterlockedDecrement
(
&
This
->
ref
);
if
(
ref
==
0
)
{
xmlXPathFreeObject
(
This
->
result
);
xmldoc_release
(
This
->
node
->
doc
);
CoTaskMemFree
(
This
);
}
return
ref
;
}
static
HRESULT
WINAPI
queryresult_GetTypeInfoCount
(
IXMLDOMNodeList
*
iface
,
UINT
*
pctinfo
)
{
FIXME
(
"
\n
"
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
queryresult_GetTypeInfo
(
IXMLDOMNodeList
*
iface
,
UINT
iTInfo
,
LCID
lcid
,
ITypeInfo
**
ppTInfo
)
{
FIXME
(
"
\n
"
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
queryresult_GetIDsOfNames
(
IXMLDOMNodeList
*
iface
,
REFIID
riid
,
LPOLESTR
*
rgszNames
,
UINT
cNames
,
LCID
lcid
,
DISPID
*
rgDispId
)
{
FIXME
(
"
\n
"
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
queryresult_Invoke
(
IXMLDOMNodeList
*
iface
,
DISPID
dispIdMember
,
REFIID
riid
,
LCID
lcid
,
WORD
wFlags
,
DISPPARAMS
*
pDispParams
,
VARIANT
*
pVarResult
,
EXCEPINFO
*
pExcepInfo
,
UINT
*
puArgErr
)
{
FIXME
(
"
\n
"
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
queryresult_get_item
(
IXMLDOMNodeList
*
iface
,
long
index
,
IXMLDOMNode
**
listItem
)
{
queryresult
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
TRACE
(
"%p %ld
\n
"
,
This
,
index
);
*
listItem
=
NULL
;
if
(
index
<
0
||
index
>=
This
->
result
->
nodesetval
->
nodeNr
)
return
S_FALSE
;
*
listItem
=
create_node
(
This
->
result
->
nodesetval
->
nodeTab
[
index
]);
return
S_OK
;
}
static
HRESULT
WINAPI
queryresult_get_length
(
IXMLDOMNodeList
*
iface
,
long
*
listLength
)
{
queryresult
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
TRACE
(
"%p
\n
"
,
This
);
*
listLength
=
This
->
result
->
nodesetval
->
nodeNr
;
return
S_OK
;
}
static
HRESULT
WINAPI
queryresult_nextNode
(
IXMLDOMNodeList
*
iface
,
IXMLDOMNode
**
nextItem
)
{
queryresult
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
TRACE
(
"%p %p
\n
"
,
This
,
nextItem
);
*
nextItem
=
NULL
;
if
(
This
->
resultPos
>=
This
->
result
->
nodesetval
->
nodeNr
)
return
S_FALSE
;
*
nextItem
=
create_node
(
This
->
result
->
nodesetval
->
nodeTab
[
This
->
resultPos
]);
This
->
resultPos
++
;
return
S_OK
;
}
static
HRESULT
WINAPI
queryresult_reset
(
IXMLDOMNodeList
*
iface
)
{
queryresult
*
This
=
impl_from_IXMLDOMNodeList
(
iface
);
TRACE
(
"%p
\n
"
,
This
);
This
->
resultPos
=
0
;
return
S_OK
;
}
static
HRESULT
WINAPI
queryresult__newEnum
(
IXMLDOMNodeList
*
iface
,
IUnknown
**
ppUnk
)
{
FIXME
(
"
\n
"
);
return
E_NOTIMPL
;
}
static
const
struct
IXMLDOMNodeListVtbl
queryresult_vtbl
=
{
queryresult_QueryInterface
,
queryresult_AddRef
,
queryresult_Release
,
queryresult_GetTypeInfoCount
,
queryresult_GetTypeInfo
,
queryresult_GetIDsOfNames
,
queryresult_Invoke
,
queryresult_get_item
,
queryresult_get_length
,
queryresult_nextNode
,
queryresult_reset
,
queryresult__newEnum
,
};
#endif
dlls/msxml3/tests/Makefile.in
View file @
e1cbec75
...
@@ -3,7 +3,7 @@ TOPOBJDIR = ../../..
...
@@ -3,7 +3,7 @@ TOPOBJDIR = ../../..
SRCDIR
=
@srcdir@
SRCDIR
=
@srcdir@
VPATH
=
@srcdir@
VPATH
=
@srcdir@
TESTDLL
=
msxml3.dll
TESTDLL
=
msxml3.dll
IMPORTS
=
oleaut32 ole32 kernel32
IMPORTS
=
oleaut32 ole32
user32
kernel32
EXTRALIBS
=
-luuid
EXTRALIBS
=
-luuid
CTESTS
=
\
CTESTS
=
\
...
...
dlls/msxml3/tests/domdoc.c
View file @
e1cbec75
...
@@ -85,6 +85,39 @@ static const WCHAR szComplete5[] = {
...
@@ -85,6 +85,39 @@ static const WCHAR szComplete5[] = {
'<'
,
'/'
,
'S'
,
':'
,
's'
,
'e'
,
'a'
,
'r'
,
'c'
,
'h'
,
'>'
,
0
'<'
,
'/'
,
'S'
,
':'
,
's'
,
'e'
,
'a'
,
'r'
,
'c'
,
'h'
,
'>'
,
0
};
};
static
const
CHAR
szExampleXML
[]
=
"<?xml version='1.0' encoding='utf-8'?>
\n
"
"<root xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>
\n
"
" <elem>
\n
"
" <a>A1 field</a>
\n
"
" <b>B1 field</b>
\n
"
" <c>C1 field</c>
\n
"
" <description xmlns:foo='http://www.winehq.org' xmlns:bar='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>
\n
"
" <html xmlns='http://www.w3.org/1999/xhtml'>
\n
"
" This is <strong>a</strong> <i>description</i>. <bar:x/>
\n
"
" </html>
\n
"
" </description>
\n
"
" </elem>
\n
"
"
\n
"
" <elem>
\n
"
" <a>A2 field</a>
\n
"
" <b>B2 field</b>
\n
"
" <c type=
\"
old
\"
>C2 field</c>
\n
"
" </elem>
\n
"
"
\n
"
" <elem xmlns='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>
\n
"
" <a>A3 field</a>
\n
"
" <b>B3 field</b>
\n
"
" <c>C3 field</c>
\n
"
" </elem>
\n
"
"
\n
"
" <elem>
\n
"
" <a>A4 field</a>
\n
"
" <b>B4 field</b>
\n
"
" <foo:c>C4 field</foo:c>
\n
"
" </elem>
\n
"
"</root>
\n
"
;
static
const
WCHAR
szNonExistentFile
[]
=
{
static
const
WCHAR
szNonExistentFile
[]
=
{
'c'
,
':'
,
'\\'
,
'N'
,
'o'
,
'n'
,
'e'
,
'x'
,
'i'
,
's'
,
't'
,
'e'
,
'n'
,
't'
,
'.'
,
'x'
,
'm'
,
'l'
,
0
'c'
,
':'
,
'\\'
,
'N'
,
'o'
,
'n'
,
'e'
,
'x'
,
'i'
,
's'
,
't'
,
'e'
,
'n'
,
't'
,
'.'
,
'x'
,
'm'
,
'l'
,
0
};
};
...
@@ -155,6 +188,142 @@ static VARIANT _variantbstr_(const char *str)
...
@@ -155,6 +188,142 @@ static VARIANT _variantbstr_(const char *str)
return
v
;
return
v
;
}
}
static
void
get_str_for_type
(
DOMNodeType
type
,
char
*
buf
)
{
switch
(
type
)
{
case
NODE_ATTRIBUTE
:
strcpy
(
buf
,
"A"
);
break
;
case
NODE_ELEMENT
:
strcpy
(
buf
,
"E"
);
break
;
case
NODE_DOCUMENT
:
strcpy
(
buf
,
"D"
);
break
;
default:
wsprintfA
(
buf
,
"[%d]"
,
type
);
}
}
static
int
get_node_position
(
IXMLDOMNode
*
node
)
{
HRESULT
r
;
int
pos
=
0
;
IXMLDOMNode_AddRef
(
node
);
do
{
IXMLDOMNode
*
new_node
;
pos
++
;
r
=
IXMLDOMNode_get_previousSibling
(
node
,
&
new_node
);
ok
(
!
FAILED
(
r
),
"get_previousSibling failed
\n
"
);
IXMLDOMNode_Release
(
node
);
node
=
new_node
;
}
while
(
r
==
S_OK
);
return
pos
;
}
static
void
node_to_string
(
IXMLDOMNode
*
node
,
char
*
buf
)
{
HRESULT
r
=
S_OK
;
DOMNodeType
type
;
if
(
node
==
NULL
)
{
lstrcpyA
(
buf
,
"(null)"
);
return
;
}
IXMLDOMNode_AddRef
(
node
);
while
(
r
==
S_OK
)
{
IXMLDOMNode
*
new_node
;
ole_check
(
IXMLDOMNode_get_nodeType
(
node
,
&
type
));
get_str_for_type
(
type
,
buf
);
buf
+=
strlen
(
buf
);
if
(
type
==
NODE_ATTRIBUTE
)
{
BSTR
bstr
;
ole_check
(
IXMLDOMNode_get_nodeName
(
node
,
&
bstr
));
*
(
buf
++
)
=
'\''
;
wsprintfA
(
buf
,
"%ws"
,
bstr
);
buf
+=
strlen
(
buf
);
*
(
buf
++
)
=
'\''
;
SysFreeString
(
bstr
);
r
=
IXMLDOMNode_selectSingleNode
(
node
,
_bstr_
(
".."
),
&
new_node
);
}
else
{
int
pos
=
get_node_position
(
node
);
DOMNodeType
parent_type
=
NODE_INVALID
;
r
=
IXMLDOMNode_get_parentNode
(
node
,
&
new_node
);
/* currently wine doesn't create a node for the <?xml ... ?>. To be able to test query
* results we "fix" it */
if
(
r
==
S_OK
)
ole_check
(
IXMLDOMNode_get_nodeType
(
node
,
&
parent_type
));
/* we need also to workaround the no document node problem - see below */
if
(((
r
==
S_FALSE
&&
type
!=
NODE_DOCUMENT
)
||
parent_type
==
NODE_DOCUMENT
)
&&
type
!=
NODE_PROCESSING_INSTRUCTION
&&
pos
==
1
)
{
todo_wine
ok
(
FALSE
,
"The first child of the document node in MSXML is the <?xml ... ?> processing instruction
\n
"
);
pos
++
;
}
wsprintf
(
buf
,
"%d"
,
pos
);
buf
+=
strlen
(
buf
);
}
ok
(
!
FAILED
(
r
),
"get_parentNode failed (%08x)
\n
"
,
r
);
IXMLDOMNode_Release
(
node
);
node
=
new_node
;
if
(
r
==
S_OK
)
*
(
buf
++
)
=
'.'
;
}
/* currently we can't access document node in wine. All our examples this is the
* root node so to be able to test query results we add it */
if
(
type
!=
NODE_DOCUMENT
)
{
todo_wine
ok
(
FALSE
,
"Document node is not the last returned node!
\n
"
);
*
(
buf
++
)
=
'.'
;
*
(
buf
++
)
=
'D'
;
*
(
buf
++
)
=
'1'
;
}
*
buf
=
0
;
}
static
char
*
list_to_string
(
IXMLDOMNodeList
*
list
)
{
static
char
buf
[
4096
];
char
*
pos
=
buf
;
long
len
=
0
;
int
i
;
if
(
list
==
NULL
)
{
lstrcpyA
(
buf
,
"(null)"
);
return
buf
;
}
ole_check
(
IXMLDOMNodeList_get_length
(
list
,
&
len
));
for
(
i
=
0
;
i
<
len
;
i
++
)
{
IXMLDOMNode
*
node
;
if
(
i
>
0
)
*
(
pos
++
)
=
' '
;
ole_check
(
IXMLDOMNodeList_nextNode
(
list
,
&
node
));
node_to_string
(
node
,
pos
);
pos
+=
strlen
(
pos
);
IXMLDOMNode_Release
(
node
);
}
*
pos
=
0
;
return
buf
;
}
#define expect_list_and_release(list, expstr) { char *str = list_to_string(list); ok(strcmp(str, expstr)==0, "Invalid node list: %s, exptected %s\n", str, expstr); if (list) IXMLDOMNodeList_Release(list); }
static
void
test_domdoc
(
void
)
static
void
test_domdoc
(
void
)
{
{
HRESULT
r
;
HRESULT
r
;
...
@@ -1272,6 +1441,86 @@ static void test_IXMLDOMDocument2(void)
...
@@ -1272,6 +1441,86 @@ static void test_IXMLDOMDocument2(void)
free_bstrs
();
free_bstrs
();
}
}
static
void
test_XPath
()
{
HRESULT
r
;
VARIANT_BOOL
b
;
IXMLDOMDocument2
*
doc
;
IXMLDOMNode
*
rootNode
;
IXMLDOMNode
*
elem1Node
;
IXMLDOMNodeList
*
list
;
r
=
CoCreateInstance
(
&
CLSID_DOMDocument
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IXMLDOMDocument2
,
(
LPVOID
*
)
&
doc
);
if
(
r
!=
S_OK
)
return
;
ole_check
(
IXMLDOMDocument_loadXML
(
doc
,
_bstr_
(
szExampleXML
),
&
b
));
ok
(
b
==
VARIANT_TRUE
,
"failed to load XML string
\n
"
);
/* switch to XPath */
ole_check
(
IXMLDOMDocument2_setProperty
(
doc
,
_bstr_
(
"SelectionLanguage"
),
_variantbstr_
(
"XPath"
)));
/* some simple queries*/
ole_check
(
IXMLDOMDocument_selectNodes
(
doc
,
_bstr_
(
"root"
),
&
list
));
ole_check
(
IXMLDOMNodeList_get_item
(
list
,
0
,
&
rootNode
));
ole_check
(
IXMLDOMNodeList_reset
(
list
));
expect_list_and_release
(
list
,
"E2.D1"
);
if
(
rootNode
==
NULL
)
return
;
ole_check
(
IXMLDOMDocument_selectNodes
(
doc
,
_bstr_
(
"root//c"
),
&
list
));
expect_list_and_release
(
list
,
"E3.E1.E2.D1 E3.E2.E2.D1"
);
ole_check
(
IXMLDOMDocument_selectNodes
(
doc
,
_bstr_
(
"//c[@type]"
),
&
list
));
expect_list_and_release
(
list
,
"E3.E2.E2.D1"
);
ole_check
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"elem"
),
&
list
));
expect_list_and_release
(
list
,
"E1.E2.D1 E2.E2.D1 E4.E2.D1"
);
ole_check
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"."
),
&
list
));
expect_list_and_release
(
list
,
"E2.D1"
);
ole_check
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"elem[3]/preceding-sibling::*"
),
&
list
));
ole_check
(
IXMLDOMNodeList_get_item
(
list
,
0
,
&
elem1Node
));
ole_check
(
IXMLDOMNodeList_reset
(
list
));
expect_list_and_release
(
list
,
"E1.E2.D1 E2.E2.D1 E3.E2.D1"
);
/* select an attribute */
ole_check
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
".//@type"
),
&
list
));
expect_list_and_release
(
list
,
"A'type'.E3.E2.E2.D1"
);
/* would evaluate to a number */
ole_expect
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"count(*)"
),
&
list
),
E_FAIL
);
/* would evaluate to a boolean */
ole_expect
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"position()>0"
),
&
list
),
E_FAIL
);
/* would evaluate to a string */
ole_expect
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"name()"
),
&
list
),
E_FAIL
);
/* no results */
ole_check
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
"c"
),
&
list
));
expect_list_and_release
(
list
,
""
);
ole_check
(
IXMLDOMDocument_selectNodes
(
doc
,
_bstr_
(
"elem//c"
),
&
list
));
expect_list_and_release
(
list
,
""
);
ole_check
(
IXMLDOMDocument_selectNodes
(
doc
,
_bstr_
(
"//elem[4]"
),
&
list
));
expect_list_and_release
(
list
,
""
);
/* foo undeclared in document node */
ole_expect
(
IXMLDOMDocument_selectNodes
(
doc
,
_bstr_
(
"root//foo:c"
),
&
list
),
E_FAIL
);
/* undeclared in <root> node */
ole_expect
(
IXMLDOMNode_selectNodes
(
rootNode
,
_bstr_
(
".//foo:c"
),
&
list
),
E_FAIL
);
/* undeclared in <elem> node */
ole_expect
(
IXMLDOMNode_selectNodes
(
elem1Node
,
_bstr_
(
"//foo:c"
),
&
list
),
E_FAIL
);
/* but this trick can be used */
ole_check
(
IXMLDOMNode_selectNodes
(
elem1Node
,
_bstr_
(
"//*[name()='foo:c']"
),
&
list
));
expect_list_and_release
(
list
,
"E3.E4.E2.D1"
);
IXMLDOMNode_Release
(
rootNode
);
IXMLDOMNode_Release
(
elem1Node
);
IXMLDOMDocument_Release
(
doc
);
free_bstrs
();
}
START_TEST
(
domdoc
)
START_TEST
(
domdoc
)
{
{
HRESULT
r
;
HRESULT
r
;
...
@@ -1289,6 +1538,7 @@ START_TEST(domdoc)
...
@@ -1289,6 +1538,7 @@ START_TEST(domdoc)
test_removeChild
();
test_removeChild
();
test_XMLHTTP
();
test_XMLHTTP
();
test_IXMLDOMDocument2
();
test_IXMLDOMDocument2
();
test_XPath
();
CoUninitialize
();
CoUninitialize
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment