From: Nikolay Sivov Subject: [PATCH 05/14] xmllite: Keep namespace list updated when going through document tree Message-Id: <20161209133834.699-5-nsivov@codeweavers.com> Date: Fri, 9 Dec 2016 16:38:25 +0300 In-Reply-To: <20161209133834.699-1-nsivov@codeweavers.com> References: <20161209133834.699-1-nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov --- 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) -- 2.10.2