v4: Create special XML_ELEMENT_NODE for PI node attributes to avoid hitting a libxml2 limitation and manual properties management.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/msxml3/nodemap.c | 4 +- dlls/msxml3/pi.c | 114 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/dlls/msxml3/nodemap.c b/dlls/msxml3/nodemap.c index 5ea083c4495..856f407654a 100644 --- a/dlls/msxml3/nodemap.c +++ b/dlls/msxml3/nodemap.c @@ -141,7 +141,7 @@ static ULONG WINAPI xmlnodemap_Release( if ( ref == 0 ) { xmlnode_release( This->node ); - xmldoc_release( This->node->doc ); + if (This->node->doc) xmldoc_release( This->node->doc ); if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant); heap_free( This ); } @@ -452,7 +452,7 @@ IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
xmlnode_add_ref(node); - xmldoc_add_ref(node->doc); + if (node->doc) xmldoc_add_ref(node->doc);
return &This->IXMLDOMNamedNodeMap_iface; } diff --git a/dlls/msxml3/pi.c b/dlls/msxml3/pi.c index cea95708087..6bacff12027 100644 --- a/dlls/msxml3/pi.c +++ b/dlls/msxml3/pi.c @@ -34,6 +34,7 @@ #include "ole2.h" #include "msxml6.h"
+#include "xmlparser.h" #include "msxml_private.h"
#include "wine/debug.h" @@ -45,6 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); typedef struct _dom_pi { xmlnode node; + xmlNodePtr attributes; IXMLDOMProcessingInstruction IXMLDOMProcessingInstruction_iface; LONG ref; } dom_pi; @@ -114,6 +116,7 @@ static ULONG WINAPI dom_pi_Release( TRACE("(%p)->(%d)\n", This, ref); if ( ref == 0 ) { + xmlFreeNode(This->attributes); destroy_xmlnode(&This->node); heap_free( This ); } @@ -287,6 +290,107 @@ static HRESULT WINAPI dom_pi_get_nextSibling( return node_get_next_sibling(&This->node, domNode); }
+static HRESULT xml_get_value(xmlChar **p, xmlChar **value) +{ + xmlChar *v; + int len; + + while (isspace(**p)) *p += 1; + if (**p != '=') return XML_E_MISSINGEQUALS; + *p += 1; + + while (isspace(**p)) *p += 1; + if (**p != '"') return XML_E_MISSINGQUOTE; + *p += 1; + + v = *p; + while (**p && **p != '"') *p += 1; + if (!**p) return XML_E_EXPECTINGCLOSEQUOTE; + len = *p - v; + if (!len) return XML_E_MISSINGNAME; + *p += 1; + + *value = heap_alloc(len + 1); + if (!*value) return E_OUTOFMEMORY; + memcpy(*value, v, len); + *(*value + len) = 0; + + return S_OK; +} + +static HRESULT parse_xml_decl(dom_pi *This) +{ + xmlChar *version, *encoding, *standalone, *p; + xmlAttrPtr attr; + HRESULT hr = S_OK; + + if (!This->node.node->content || This->attributes->properties) + return S_OK; + + version = encoding = standalone = NULL; + + p = This->node.node->content; + + while (*p) + { + while (isspace(*p)) p++; + if (!*p) break; + + if (!strncmp((const char *)p, "version", 7)) + { + p += 7; + if ((hr = xml_get_value(&p, &version)) != S_OK) goto fail; + } + else if (!strncmp((const char *)p, "encoding", 8)) + { + p += 8; + if ((hr = xml_get_value(&p, &encoding)) != S_OK) goto fail; + } + else if (!strncmp((const char *)p, "standalone", 10)) + { + p += 10; + if ((hr = xml_get_value(&p, &standalone)) != S_OK) goto fail; + } + else + { + FIXME("unexpected XML attribute %s\n", debugstr_a((const char *)p)); + hr = XML_E_UNEXPECTED_ATTRIBUTE; + goto fail; + } + } + + if (version) + { + attr = xmlSetNsProp(This->attributes, NULL, (const xmlChar *)"version", version); + if (!attr) + hr = E_OUTOFMEMORY; + } + if (encoding) + { + attr = xmlSetNsProp(This->attributes, NULL, (const xmlChar *)"encoding", encoding); + if (!attr) + hr = E_OUTOFMEMORY; + } + if (standalone) + { + attr = xmlSetNsProp(This->attributes, NULL, (const xmlChar *)"standalone", standalone); + if (!attr) + hr = E_OUTOFMEMORY; + } + +fail: + if (hr != S_OK) + { + xmlFreePropList(This->attributes->properties); + This->attributes->properties = NULL; + } + + heap_free(version); + heap_free(encoding); + heap_free(standalone); + return hr; +} + static HRESULT WINAPI dom_pi_get_attributes( IXMLDOMProcessingInstruction *iface, IXMLDOMNamedNodeMap** map) @@ -307,8 +411,10 @@ static HRESULT WINAPI dom_pi_get_attributes(
if (!strcmpW(name, xmlW)) { - FIXME("created dummy map for <?xml ?>\n"); - *map = create_nodemap(This->node.node, &dom_pi_attr_map); + hr = parse_xml_decl(This); + if (hr != S_OK) return S_FALSE; + + *map = create_nodemap(This->attributes, &dom_pi_attr_map); SysFreeString(name); return S_OK; } @@ -761,6 +867,10 @@ IUnknown* create_pi( xmlNodePtr pi )
This->IXMLDOMProcessingInstruction_iface.lpVtbl = &dom_pi_vtbl; This->ref = 1; + /* xmlSetProp/xmlSetNsProp accept only nodes of type XML_ELEMENT_NODE, + * so we have to create special node for attributes. + */ + This->attributes = xmlNewNode(NULL, (const xmlChar *)"attributes");
init_xmlnode(&This->node, pi, (IXMLDOMNode*)&This->IXMLDOMProcessingInstruction_iface, &dompi_dispex);