Commit d461d7d2 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Create additional node for xml declaration.

parent 5afe1662
...@@ -141,18 +141,75 @@ static xmldoc_priv * create_priv(void) ...@@ -141,18 +141,75 @@ static xmldoc_priv * create_priv(void)
return priv; 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 ) static xmlDocPtr doparse( char *ptr, int len, const char *encoding )
{ {
xmlDocPtr doc;
#ifdef HAVE_XMLREADMEMORY #ifdef HAVE_XMLREADMEMORY
/* /*
* use xmlReadMemory if possible so we can suppress * use xmlReadMemory if possible so we can suppress
* writing errors to stderr * writing errors to stderr
*/ */
return xmlReadMemory( ptr, len, NULL, encoding, doc = xmlReadMemory( ptr, len, NULL, encoding,
XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS ); XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOBLANKS );
#else #else
return xmlParseMemory( ptr, len ); doc = xmlParseMemory( ptr, len );
#endif #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) LONG xmldoc_add_ref(xmlDocPtr doc)
...@@ -345,7 +402,7 @@ static HRESULT WINAPI xmldoc_IPersistStream_Load( ...@@ -345,7 +402,7 @@ static HRESULT WINAPI xmldoc_IPersistStream_Load(
len = GlobalSize(hglobal); len = GlobalSize(hglobal);
ptr = GlobalLock(hglobal); ptr = GlobalLock(hglobal);
if (len != 0) if (len != 0)
xmldoc = parse_xml(ptr, len); xmldoc = doparse(ptr, len, NULL);
GlobalUnlock(hglobal); GlobalUnlock(hglobal);
if (!xmldoc) if (!xmldoc)
...@@ -1524,7 +1581,7 @@ static HRESULT WINAPI domdoc_load( ...@@ -1524,7 +1581,7 @@ static HRESULT WINAPI domdoc_load(
{ {
*isSuccessful = VARIANT_TRUE; *isSuccessful = VARIANT_TRUE;
TRACE("Using ID_IStream to load Document\n"); TRACE("Using IStream to load Document\n");
return S_OK; return S_OK;
} }
else else
...@@ -1733,6 +1790,7 @@ static HRESULT WINAPI domdoc_save( ...@@ -1733,6 +1790,7 @@ static HRESULT WINAPI domdoc_save(
domdoc *This = impl_from_IXMLDOMDocument2( iface ); domdoc *This = impl_from_IXMLDOMDocument2( iface );
HANDLE handle; HANDLE handle;
xmlSaveCtxtPtr ctx; xmlSaveCtxtPtr ctx;
xmlNodePtr xmldecl;
HRESULT ret = S_OK; HRESULT ret = S_OK;
TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination), TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination),
...@@ -1788,7 +1846,10 @@ static HRESULT WINAPI domdoc_save( ...@@ -1788,7 +1846,10 @@ static HRESULT WINAPI domdoc_save(
return S_FALSE; return S_FALSE;
} }
xmldecl = xmldoc_unlink_xmldecl(get_doc(This));
if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE; if (xmlSaveDoc(ctx, get_doc(This)) == -1) ret = S_FALSE;
xmldoc_link_xmldecl(get_doc(This), xmldecl);
/* will close file through close callback */ /* will close file through close callback */
xmlSaveClose(ctx); xmlSaveClose(ctx);
......
...@@ -134,6 +134,8 @@ extern LONG xmldoc_add_ref( xmlDocPtr doc ); ...@@ -134,6 +134,8 @@ extern LONG xmldoc_add_ref( xmlDocPtr doc );
extern LONG xmldoc_release( xmlDocPtr doc ); extern LONG xmldoc_release( xmlDocPtr doc );
extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ); extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node );
extern HRESULT xmldoc_remove_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 ); extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own );
......
...@@ -1382,6 +1382,7 @@ static HRESULT WINAPI xmlnode_get_xml( ...@@ -1382,6 +1382,7 @@ static HRESULT WINAPI xmlnode_get_xml(
{ {
xmlnode *This = impl_from_IXMLDOMNode( iface ); xmlnode *This = impl_from_IXMLDOMNode( iface );
xmlBufferPtr pXmlBuf; xmlBufferPtr pXmlBuf;
xmlNodePtr xmldecl;
int nSize; int nSize;
TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString); TRACE("(%p %d)->(%p)\n", This, This->node->type, xmlString);
...@@ -1391,6 +1392,8 @@ static HRESULT WINAPI xmlnode_get_xml( ...@@ -1391,6 +1392,8 @@ static HRESULT WINAPI xmlnode_get_xml(
*xmlString = NULL; *xmlString = NULL;
xmldecl = xmldoc_unlink_xmldecl( This->node->doc );
pXmlBuf = xmlBufferCreate(); pXmlBuf = xmlBufferCreate();
if(pXmlBuf) if(pXmlBuf)
{ {
...@@ -1424,6 +1427,8 @@ static HRESULT WINAPI xmlnode_get_xml( ...@@ -1424,6 +1427,8 @@ static HRESULT WINAPI xmlnode_get_xml(
xmlBufferFree(pXmlBuf); xmlBufferFree(pXmlBuf);
} }
xmldoc_link_xmldecl( This->node->doc, xmldecl );
/* Always returns a string. */ /* Always returns a string. */
if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 ); if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 );
......
...@@ -470,20 +470,8 @@ static void node_to_string(IXMLDOMNode *node, char *buf) ...@@ -470,20 +470,8 @@ static void node_to_string(IXMLDOMNode *node, char *buf)
} }
else else
{ {
int pos = get_node_position(node);
DOMNodeType parent_type = NODE_INVALID;
r = IXMLDOMNode_get_parentNode(node, &new_node); r = IXMLDOMNode_get_parentNode(node, &new_node);
wsprintf(buf, "%d", get_node_position(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);
buf += strlen(buf); buf += strlen(buf);
} }
...@@ -2477,6 +2465,40 @@ static void test_get_childNodes(void) ...@@ -2477,6 +2465,40 @@ static void test_get_childNodes(void)
IXMLDOMDocument_Release( doc ); 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) static void test_removeChild(void)
{ {
HRESULT r; HRESULT r;
...@@ -5581,6 +5603,7 @@ START_TEST(domdoc) ...@@ -5581,6 +5603,7 @@ START_TEST(domdoc)
test_getElementsByTagName(); test_getElementsByTagName();
test_get_text(); test_get_text();
test_get_childNodes(); test_get_childNodes();
test_get_firstChild();
test_removeChild(); test_removeChild();
test_replaceChild(); test_replaceChild();
test_removeNamedItem(); test_removeNamedItem();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment