[PATCH 8/8] msxml3: Implement XSLPattern collection methods

Adam Martinson amartinson at codeweavers.com
Thu Oct 28 20:22:22 CDT 2010


---
 dlls/msxml3/tests/domdoc.c |  225 ++++++++++++++++++--------------------------
 dlls/msxml3/xslpattern.y   |  106 +++++++++++++++++++--
 2 files changed, 185 insertions(+), 146 deletions(-)

diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 5b35070..fe35494 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -6571,136 +6571,100 @@ static void test_XSLPattern(void)
     list = NULL;
 
     /* attribute() */
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("attribute()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len == 0, "expected empty list\n");
-        if (len)
-            IXMLDOMNodeList_Release(list);
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("attribute()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len == 0, "expected empty list\n");
+    if (len)
+        IXMLDOMNodeList_Release(list);
 
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("attribute('depth')"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len == 0, "expected empty list\n");
-        if (len)
-            IXMLDOMNodeList_Release(list);
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("attribute('depth')"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len == 0, "expected empty list\n");
+    if (len)
+        IXMLDOMNodeList_Release(list);
 
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/attribute('depth')"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "A'depth'.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/attribute('depth')"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "A'depth'.E3.D1");
 
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//x/attribute()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "A'id'.E3.E3.D1 A'depth'.E3.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//x/attribute()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "A'id'.E3.E3.D1 A'depth'.E3.E3.D1");
 
     list = NULL;
     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("//x//attribute(id)"), &list), E_FAIL);
     if (list)
         IXMLDOMNodeList_Release(list);
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//x//attribute('id')"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "A'id'.E3.E3.D1 A'id'.E4.E3.E3.D1 A'id'.E5.E3.E3.D1 A'id'.E6.E3.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//x//attribute('id')"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "A'id'.E3.E3.D1 A'id'.E4.E3.E3.D1 A'id'.E5.E3.E3.D1 A'id'.E6.E3.E3.D1");
 
     /* comment() */
     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("comment()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        ok(len != 0, "expected filled list\n");
-        if (len)
-            expect_list_and_release(list, "C2.D1");
-    }
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "C2.D1");
 
     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//comment()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        ok(len != 0, "expected filled list\n");
-        if (len)
-            expect_list_and_release(list, "C2.D1 C1.E3.D1 C2.E3.E3.D1 C2.E4.E3.D1");
-    }
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "C2.D1 C1.E3.D1 C2.E3.E3.D1 C2.E4.E3.D1");
 
     /* element() */
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("element()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("element()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "E3.D1");
 
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/y/element()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "E4.E4.E3.D1 E5.E4.E3.D1 E6.E4.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/y/element()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "E4.E4.E3.D1 E5.E4.E3.D1 E6.E4.E3.D1");
 
     list = NULL;
     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("//element(a)"), &list), E_FAIL);
     if (list)
         IXMLDOMNodeList_Release(list);
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//element('a')"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "E4.E3.E3.D1 E4.E4.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//element('a')"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "E4.E3.E3.D1 E4.E4.E3.D1");
 
     /* node() */
     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("node()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        ok(len != 0, "expected filled list\n");
-        if (len)
-            expect_list_and_release(list, "P1.D1 C2.D1 E3.D1");
-    }
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "P1.D1 C2.D1 E3.D1");
 
     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//x/node()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        ok(len != 0, "expected filled list\n");
-        if (len)
-            expect_list_and_release(list, "P1.E3.E3.D1 C2.E3.E3.D1 T3.E3.E3.D1 E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1");
-    }
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "P1.E3.E3.D1 C2.E3.E3.D1 T3.E3.E3.D1 E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1");
 
     /* nodeType() */
     /* XML_ELEMENT_NODE */
@@ -6730,49 +6694,40 @@ static void test_XSLPattern(void)
     ole_check(IXMLDOMNodeList_get_length(list, &len));
     ok(len != 0, "expected filled list\n");
     if (len)
-        expect_list_and_release(list, "T3.E3.E3.D1");
+        expect_list_and_release(list, "C2.E3.E3.D1");
 
     /* pi() */
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("pi()"), &list));
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("pi()"), &list));
     if (list)
     {
         len = 0;
         ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
+        ok(len != 0, "expected filled list\n");
         if (len)
-            todo_wine expect_list_and_release(list, "P1.D1");
+            expect_list_and_release(list, "P1.D1");
     }
 
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//y/pi()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "P1.E4.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//y/pi()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "P1.E4.E3.D1");
 
     /* textnode() */
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/textnode()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "T2.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/textnode()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "T2.E3.D1");
 
-    todo_wine ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/element()/textnode()"), &list));
-    if (list)
-    {
-        len = 0;
-        ole_check(IXMLDOMNodeList_get_length(list, &len));
-        todo_wine ok(len != 0, "expected filled list\n");
-        if (len)
-            todo_wine expect_list_and_release(list, "T3.E3.E3.D1 T3.E4.E3.D1");
-    }
+    ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root/element()/textnode()"), &list));
+    len = 0;
+    ole_check(IXMLDOMNodeList_get_length(list, &len));
+    ok(len != 0, "expected filled list\n");
+    if (len)
+        expect_list_and_release(list, "T3.E3.E3.D1 T3.E4.E3.D1");
 
     IXMLDOMDocument2_Release(doc);
     free_bstrs();
diff --git a/dlls/msxml3/xslpattern.y b/dlls/msxml3/xslpattern.y
index e5d4449..958956e 100644
--- a/dlls/msxml3/xslpattern.y
+++ b/dlls/msxml3/xslpattern.y
@@ -34,6 +34,13 @@ static const xmlChar NameTest_mod_post[] = "']";
 
 #define U(str) BAD_CAST str
 
+static inline BOOL is_literal(xmlChar const* tok)
+{
+    return (tok && tok[0] && tok[1] &&
+            tok[0]== tok[xmlStrlen(tok)-1] &&
+            (tok[0] == '\'' || tok[0] == '"'));
+}
+
 %}
 
 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
@@ -118,7 +125,7 @@ static const xmlChar NameTest_mod_post[] = "']";
                             | AbbreviatedRelativeLocationPath
     ;
     /* [2.1] Location Steps */
-    Step                    : AxisSpecifier NameTest Predicates
+    Step                    : AxisSpecifier NodeTest Predicates
                             {
                                 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3);
                                 $$=$1;
@@ -127,21 +134,21 @@ static const xmlChar NameTest_mod_post[] = "']";
                                 $$=xmlStrcat($$,$3);
                                 xmlFree($3);
                             }
-                            | NameTest Predicates
+                            | NodeTest Predicates
                             {
                                 TRACE("Got Step: \"%s%s\"\n", $1, $2);
                                 $$=$1;
                                 $$=xmlStrcat($$,$2);
                                 xmlFree($2);
                             }
-                            | AxisSpecifier NameTest
+                            | AxisSpecifier NodeTest
                             {
                                 TRACE("Got Step: \"%s%s\"\n", $1, $2);
                                 $$=$1;
                                 $$=xmlStrcat($$,$2);
                                 xmlFree($2);
                             }
-                            | NameTest
+                            | NodeTest
                             | Attribute
                             | AbbreviatedStep
     ;
@@ -162,6 +169,9 @@ static const xmlChar NameTest_mod_post[] = "']";
     ;
 
     /* [2.3] Node Tests */
+    NodeTest                : NameTest
+                            | FunctionCall
+    ;
     NameTest                : '*'
                             {
                                 TRACE("Got NameTest: \"*\"\n");
@@ -291,17 +301,91 @@ static const xmlChar NameTest_mod_post[] = "']";
     FunctionCall            : QName '(' Arguments ')'
                             {
                                 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
-                                $$=$1;
-                                $$=xmlStrcat($$,U("("));
-                                $$=xmlStrcat($$,$3);
-                                xmlFree($3);
-                                $$=xmlStrcat($$,U(")"));
+                                if (xmlStrEqual($1,U("ancestor")))
+                                {
+                                    $$=$1;
+                                    $$=xmlStrcat($$,U("::"));
+                                    $$=xmlStrcat($$,$3);
+                                    xmlFree($3);
+                                }
+                                else if (xmlStrEqual($1,U("attribute")))
+                                {
+                                    if (is_literal($3))
+                                    {
+                                        $$=xmlStrdup(U("@*[name()="));
+                                        xmlFree($1);
+                                        $$=xmlStrcat($$,$3);
+                                        xmlFree($3);
+                                        $$=xmlStrcat($$,U("]"));
+                                    }
+                                    else
+                                    {
+                                        /* XML_XPATH_INVALID_TYPE */
+                                        $$=xmlStrdup(U("error(1211, 'Error: attribute("));
+                                        xmlFree($1);
+                                        $$=xmlStrcat($$,$3);
+                                        xmlFree($3);
+                                        $$=xmlStrcat($$,U("): invalid argument"));
+                                    }
+                                }
+                                else if (xmlStrEqual($1,U("element")))
+                                {
+                                    if (is_literal($3))
+                                    {
+                                        $$=xmlStrdup(U("node()[nodeType()=1][name()="));
+                                        xmlFree($1);
+                                        $$=xmlStrcat($$,$3);
+                                        xmlFree($3);
+                                        $$=xmlStrcat($$,U("]"));
+                                    }
+                                    else
+                                    {
+                                        /* XML_XPATH_INVALID_TYPE */
+                                        $$=xmlStrdup(U("error(1211, 'Error: element("));
+                                        xmlFree($1);
+                                        $$=xmlStrcat($$,$3);
+                                        xmlFree($3);
+                                        $$=xmlStrcat($$,U("): invalid argument"));
+                                    }
+                                }
+                                else
+                                {
+                                    $$=$1;
+                                    $$=xmlStrcat($$,U("("));
+                                    $$=xmlStrcat($$,$3);
+                                    xmlFree($3);
+                                    $$=xmlStrcat($$,U(")"));
+                                }
                             }
                             | QName '(' ')'
                             {
                                 TRACE("Got FunctionCall: \"%s()\"\n", $1);
-                                $$=$1;
-                                $$=xmlStrcat($$,U("()"));
+                                /* comment() & node() work the same in XPath */
+                                if (xmlStrEqual($1,U("attribute")))
+                                {
+                                    $$=xmlStrdup(U("@*"));
+                                    xmlFree($1);
+                                }
+                                else if (xmlStrEqual($1,U("element")))
+                                {
+                                    $$=xmlStrdup(U("node()[nodeType()=1]"));
+                                    xmlFree($1);
+                                }
+                                else if (xmlStrEqual($1,U("pi")))
+                                {
+                                    $$=xmlStrdup(U("processing-instruction()"));
+                                    xmlFree($1);
+                                }
+                                else if (xmlStrEqual($1,U("textnode")))
+                                {
+                                    $$=xmlStrdup(U("text()"));
+                                    xmlFree($1);
+                                }
+                                else
+                                {
+                                    $$=$1;
+                                    $$=xmlStrcat($$,U("()"));
+                                }
                             }
     ;
     Arguments               : Argument ',' Arguments
-- 
1.7.2.3


--------------030403010502000903070902--



More information about the wine-patches mailing list