Nikolay Sivov : xmllite: Keep namespace list updated when going through document tree.

Alexandre Julliard julliard at winehq.org
Fri Dec 9 13:37:34 CST 2016


Module: wine
Branch: master
Commit: 65ee2b734a35f45688486e27a4329a1ea81e3f75
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=65ee2b734a35f45688486e27a4329a1ea81e3f75

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Dec  9 16:38:25 2016 +0300

xmllite: Keep namespace list updated when going through document tree.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/xmllite/reader.c | 80 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 65 insertions(+), 15 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 500db62..351f872 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -512,6 +512,23 @@ static void reader_free_element(xmlreader *reader, struct element *element)
     reader_free(reader, element);
 }
 
+static void reader_mark_ns_nodes(xmlreader *reader, struct element *element)
+{
+    struct ns *ns;
+
+    LIST_FOR_EACH_ENTRY(ns, &reader->ns, struct ns, entry) {
+        if (ns->element)
+            break;
+        ns->element = element;
+    }
+
+    LIST_FOR_EACH_ENTRY(ns, &reader->nsdef, struct ns, entry) {
+        if (ns->element)
+            break;
+        ns->element = element;
+    }
+}
+
 static HRESULT reader_push_element(xmlreader *reader, strval *prefix, strval *localname,
     strval *qname)
 {
@@ -538,6 +555,7 @@ static HRESULT reader_push_element(xmlreader *reader, strval *prefix, strval *lo
     }
 
     list_add_head(&reader->elements, &element->entry);
+    reader_mark_ns_nodes(reader, element);
     reader->is_empty_element = FALSE;
 
 failed:
@@ -545,18 +563,48 @@ failed:
     return hr;
 }
 
-static void reader_pop_element(xmlreader *reader)
+static void reader_pop_ns_nodes(xmlreader *reader, struct element *element)
 {
-    struct element *elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
+    struct ns *ns, *ns2;
 
-    if (elem)
-    {
-        list_remove(&elem->entry);
-        reader_free_strvalued(reader, &elem->qname);
-        reader_free_strvalued(reader, &elem->localname);
-        reader_free(reader, elem);
-        reader_dec_depth(reader);
+    LIST_FOR_EACH_ENTRY_SAFE_REV(ns, ns2, &reader->ns, struct ns, entry) {
+        if (ns->element != element)
+            break;
+
+        list_remove(&ns->entry);
+        reader_free_strvalued(reader, &ns->prefix);
+        reader_free_strvalued(reader, &ns->uri);
+        reader_free(reader, ns);
     }
+
+    if (!list_empty(&reader->nsdef)) {
+        ns = LIST_ENTRY(list_head(&reader->nsdef), struct ns, entry);
+        if (ns->element == element) {
+            list_remove(&ns->entry);
+            reader_free_strvalued(reader, &ns->prefix);
+            reader_free_strvalued(reader, &ns->uri);
+            reader_free(reader, ns);
+        }
+    }
+}
+
+static void reader_pop_element(xmlreader *reader)
+{
+    struct element *element;
+
+    if (list_empty(&reader->elements))
+        return;
+
+    element = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
+    list_remove(&element->entry);
+
+    reader_pop_ns_nodes(reader, element);
+    reader_free_element(reader, element);
+    reader_dec_depth(reader);
+
+    /* It was a root element, the rest is expected as Misc */
+    if (list_empty(&reader->elements))
+        reader->instate = XmlReadInState_MiscEnd;
 }
 
 /* Always make a copy, cause strings are supposed to be null terminated. Null pointer for 'value'
@@ -2139,6 +2187,7 @@ static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *loca
             reader->empty_element.prefix = *prefix;
             reader->empty_element.localname = *local;
             reader->empty_element.qname = *qname;
+            reader_mark_ns_nodes(reader, &reader->empty_element);
             return S_OK;
         }
 
@@ -2231,12 +2280,6 @@ static HRESULT reader_parse_endtag(xmlreader *reader)
     elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
     if (!strval_eq(reader, &elem->qname, &qname)) return WC_E_ELEMENTMATCH;
 
-    reader_pop_element(reader);
-
-    /* It was a root element, the rest is expected as Misc */
-    if (list_empty(&reader->elements))
-        reader->instate = XmlReadInState_MiscEnd;
-
     reader->nodetype = XmlNodeType_EndElement;
     reader_set_strvalue(reader, StringValue_Prefix, &prefix);
     reader_set_strvalue(reader, StringValue_LocalName, &local);
@@ -2415,11 +2458,18 @@ static HRESULT reader_parse_content(xmlreader *reader)
 
 static HRESULT reader_parse_nextnode(xmlreader *reader)
 {
+    XmlNodeType nodetype = reader_get_nodetype(reader);
     HRESULT hr;
 
     if (!is_reader_pending(reader))
         reader_clear_attrs(reader);
 
+    /* When moving from EndElement or empty element, pop its own namespace defitions */
+    if (nodetype == XmlNodeType_Element && reader->is_empty_element)
+        reader_pop_ns_nodes(reader, &reader->empty_element);
+    else if (nodetype == XmlNodeType_EndElement)
+        reader_pop_element(reader);
+
     while (1)
     {
         switch (reader->instate)




More information about the wine-cvs mailing list