[PATCH] Create additional node for xml declaration
Nikolay Sivov
nsivov at codeweavers.com
Mon Jun 28 03:17:56 CDT 2010
---
dlls/msxml3/domdoc.c | 73 +++++++++++++++++++++++++++++++++++++++---
dlls/msxml3/msxml_private.h | 2 +
dlls/msxml3/node.c | 5 +++
dlls/msxml3/tests/domdoc.c | 49 +++++++++++++++++++++--------
4 files changed, 110 insertions(+), 19 deletions(-)
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 54e4728..fe6e237 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -141,18 +141,75 @@ static xmldoc_priv * create_priv(void)
return priv;
}
+/* links a "<?xml" node as a first child */
+void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node)
+{
+ assert(doc != NULL);
+ if (doc->standalone != -1) xmlAddPrevSibling( doc->children, node );
+}
+
+/* unlinks a first "<?xml" child if it was created */
+xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc)
+{
+ xmlNodePtr node;
+
+ assert(doc != NULL);
+
+ if (doc->standalone != -1)
+ {
+ node = doc->children;
+ xmlUnlinkNode( node );
+ }
+ else
+ node = NULL;
+
+ return node;
+}
+
static xmlDocPtr doparse( char *ptr, int len, const char *encoding )
{
+ xmlDocPtr doc;
+
#ifdef HAVE_XMLREADMEMORY
/*
* use xmlReadMemory if possible so we can suppress
* writing errors to stderr
*/
- return xmlReadMemory( ptr, len, NULL, encoding,
- XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
-#else
- return xmlParseMemory( ptr, len );
+ doc = xmlReadMemory( ptr, len, NULL, encoding,
+ XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
+ #else
+ doc = xmlParseMemory( ptr, len );
#endif
+
+ /* create first child as a <?xml...?> */
+ if (doc && doc->standalone != -1)
+ {
+ xmlNodePtr node;
+ char buff[30];
+ xmlChar *xmlbuff = (xmlChar*)buff;
+
+ node = xmlNewDocPI( doc, (xmlChar*)"xml", NULL );
+
+ /* version attribute can't be omitted */
+ sprintf(buff, "version=\"%s\"", doc->version ? (char*)doc->version : "1.0");
+ xmlNodeAddContent( node, xmlbuff );
+
+ if (doc->encoding)
+ {
+ sprintf(buff, " encoding=\"%s\"", doc->encoding);
+ xmlNodeAddContent( node, xmlbuff );
+ }
+
+ if (doc->standalone != -2)
+ {
+ sprintf(buff, " standalone=\"%s\"", doc->standalone == 0 ? "no" : "yes");
+ xmlNodeAddContent( node, xmlbuff );
+ }
+
+ xmldoc_link_xmldecl( doc, node );
+ }
+
+ return doc;
}
LONG xmldoc_add_ref(xmlDocPtr doc)
@@ -345,7 +402,7 @@ static HRESULT WINAPI xmldoc_IPersistStream_Load(
len = GlobalSize(hglobal);
ptr = GlobalLock(hglobal);
if (len != 0)
- xmldoc = parse_xml(ptr, len);
+ xmldoc = doparse(ptr, len, NULL);
GlobalUnlock(hglobal);
if (!xmldoc)
@@ -1524,7 +1581,7 @@ static HRESULT WINAPI domdoc_load(
{
*isSuccessful = VARIANT_TRUE;
- TRACE("Using ID_IStream to load Document\n");
+ TRACE("Using IStream to load Document\n");
return S_OK;
}
else
@@ -1733,6 +1790,7 @@ static HRESULT WINAPI domdoc_save(
domdoc *This = impl_from_IXMLDOMDocument2( iface );
HANDLE handle;
xmlSaveCtxtPtr ctx;
+ xmlNodePtr xmldecl;
HRESULT ret = S_OK;
TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
@@ -1788,7 +1846,10 @@ static HRESULT WINAPI domdoc_save(
return S_FALSE;
}
+ xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
+ xmldoc_link_xmldecl(get_doc(This), xmldecl);
+
/* will close file through close callback */
xmlSaveClose(ctx);
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 1df3e8b..e0279f1 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -134,6 +134,8 @@ extern LONG xmldoc_add_ref( xmlDocPtr doc );
extern LONG xmldoc_release( xmlDocPtr doc );
extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node );
extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node );
+extern void xmldoc_link_xmldecl(xmlDocPtr doc, xmlNodePtr node);
+extern xmlNodePtr xmldoc_unlink_xmldecl(xmlDocPtr doc);
extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own );
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index 135844f..bbdcb5d 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -1382,6 +1382,7 @@ static HRESULT WINAPI xmlnode_get_xml(
{
xmlnode *This = impl_from_IXMLDOMNode( iface );
xmlBufferPtr pXmlBuf;
+ xmlNodePtr xmldecl;
int nSize;
TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString);
@@ -1391,6 +1392,8 @@ static HRESULT WINAPI xmlnode_get_xml(
*xmlString = NULL;
+ xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
+
pXmlBuf = xmlBufferCreate();
if(pXmlBuf)
{
@@ -1424,6 +1427,8 @@ static HRESULT WINAPI xmlnode_get_xml(
xmlBufferFree(pXmlBuf);
}
+ xmldoc_link_xmldecl( This->node->doc, xmldecl );
+
/* Always returns a string. */
if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 );
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 9c1440c..cde4c81 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -470,20 +470,8 @@ static void node_to_string(IXMLDOMNode *node, char *buf)
}
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(new_node, &parent_type));
- if ((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);
+ wsprintf(buf, "%d", get_node_position(node));
buf += strlen(buf);
}
@@ -2477,6 +2465,40 @@ static void test_get_childNodes(void)
IXMLDOMDocument_Release( doc );
}
+static void test_get_firstChild(void)
+{
+ static WCHAR xmlW[] = {'x','m','l',0};
+ IXMLDOMDocument *doc;
+ IXMLDOMNode *node;
+ VARIANT_BOOL b;
+ HRESULT r;
+ BSTR str;
+
+ r = CoCreateInstance( &CLSID_DOMDocument, NULL,
+ CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc );
+ ok( r == S_OK, "failed with 0x%08x\n", r );
+ if( r != S_OK )
+ return;
+
+ str = SysAllocString( szComplete4 );
+ r = IXMLDOMDocument_loadXML( doc, str, &b );
+ ok( r == S_OK, "loadXML failed\n");
+ ok( b == VARIANT_TRUE, "failed to load XML string\n");
+ SysFreeString( str );
+
+ r = IXMLDOMDocument_get_firstChild( doc, &node );
+ ok( r == S_OK, "ret %08x\n", r);
+
+ r = IXMLDOMNode_get_nodeName( node, &str );
+ ok( r == S_OK, "ret %08x\n", r);
+
+ ok(memcmp(str, xmlW, sizeof(xmlW)) == 0, "expected \"xml\" node name\n");
+
+ SysFreeString(str);
+ IXMLDOMNode_Release( node );
+ IXMLDOMDocument_Release( doc );
+}
+
static void test_removeChild(void)
{
HRESULT r;
@@ -5581,6 +5603,7 @@ START_TEST(domdoc)
test_getElementsByTagName();
test_get_text();
test_get_childNodes();
+ test_get_firstChild();
test_removeChild();
test_replaceChild();
test_removeNamedItem();
--
1.5.6.5
--------------030900040401010908080204--
More information about the wine-patches
mailing list