Nikolay Sivov : xmllite: Support CDATA nodes.

Alexandre Julliard julliard at winehq.org
Mon Mar 11 16:24:51 CDT 2013


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Mar 10 18:29:43 2013 +0400

xmllite: Support CDATA nodes.

---

 dlls/xmllite/reader.c       |   61 ++++++++++++++++++++++++++++++--
 dlls/xmllite/tests/reader.c |   83 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+), 3 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 9216127..6fd0f69 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -63,6 +63,7 @@ typedef enum
     XmlReadResumeState_Initial,
     XmlReadResumeState_PITarget,
     XmlReadResumeState_PIBody,
+    XmlReadResumeState_CDATA,
     XmlReadResumeState_Comment,
     XmlReadResumeState_STag
 } XmlReaderResumeState;
@@ -72,7 +73,7 @@ typedef enum
 {
     XmlReadResume_Name,  /* PITarget, name for NCName, prefix for QName */
     XmlReadResume_Local, /* local for QName */
-    XmlReadResume_Body,  /* PI body, comment text */
+    XmlReadResume_Body,  /* PI body, comment text, CDATA text */
     XmlReadResume_Last
 } XmlReaderResume;
 
@@ -1772,8 +1773,51 @@ static HRESULT reader_parse_endtag(xmlreader *reader)
    [21] CDEnd ::= ']]>' */
 static HRESULT reader_parse_cdata(xmlreader *reader)
 {
-    FIXME("CDATA sections are not supported\n");
-    return E_NOTIMPL;
+    WCHAR *start, *ptr;
+
+    if (reader->resume[XmlReadResume_Body])
+    {
+        start = reader->resume[XmlReadResume_Body];
+        ptr = reader_get_cur(reader);
+    }
+    else
+    {
+        /* skip markup '<![CDATA[' */
+        reader_skipn(reader, 9);
+        reader_shrink(reader);
+        ptr = start = reader_get_cur(reader);
+        reader->nodetype = XmlNodeType_CDATA;
+        reader->resume[XmlReadResume_Body] = start;
+        reader->resumestate = XmlReadResumeState_CDATA;
+        reader_set_strvalue(reader, StringValue_LocalName, NULL);
+        reader_set_strvalue(reader, StringValue_QualifiedName, NULL);
+        reader_set_strvalue(reader, StringValue_Value, NULL);
+    }
+
+    while (*ptr)
+    {
+        if (*ptr == ']' && *(ptr+1) == ']' && *(ptr+2) == '>')
+        {
+            strval value = { start, ptr-start };
+
+            TRACE("%s\n", debugstr_wn(start, ptr-start));
+            /* skip ']]>' */
+            reader_skipn(reader, 3);
+            reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
+            reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
+            reader_set_strvalue(reader, StringValue_Value, &value);
+            reader->resume[XmlReadResume_Body] = NULL;
+            reader->resumestate = XmlReadResumeState_Initial;
+            return S_OK;
+        }
+        else
+        {
+            reader_skipn(reader, 1);
+            ptr++;
+        }
+    }
+
+    return S_OK;
 }
 
 /* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
@@ -1799,6 +1843,17 @@ static HRESULT reader_parse_content(xmlreader *reader)
     static const WCHAR etagW[] = {'<','/',0};
     static const WCHAR ampW[] = {'&',0};
 
+    if (reader->resumestate != XmlReadResumeState_Initial)
+    {
+        switch (reader->resumestate)
+        {
+        case XmlReadResumeState_CDATA:
+            return reader_parse_cdata(reader);
+        default:
+            ERR("unknown resume state %d\n", reader->resumestate);
+        }
+    }
+
     reader_shrink(reader);
 
     /* handle end tag here, it indicates end of content as well */
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 9829452..7373a69 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1318,6 +1318,88 @@ todo_wine
     IXmlReader_Release(reader);
 }
 
+static struct test_entry cdata_tests[] = {
+    { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK },
+    { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK },
+    { NULL }
+};
+
+static void test_read_cdata(void)
+{
+    struct test_entry *test = cdata_tests;
+    IXmlReader *reader;
+    HRESULT hr;
+
+    hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
+    ok(hr == S_OK, "S_OK, got %08x\n", hr);
+
+    while (test->xml)
+    {
+        XmlNodeType type;
+        IStream *stream;
+
+        stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
+        hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
+        ok(hr == S_OK, "got %08x\n", hr);
+
+        type = XmlNodeType_None;
+        hr = IXmlReader_Read(reader, &type);
+
+        /* read one more to get to CDATA */
+        if (type == XmlNodeType_Element)
+        {
+            type = XmlNodeType_None;
+            hr = IXmlReader_Read(reader, &type);
+        }
+
+        if (test->hr_broken)
+            ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
+        else
+            ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
+        if (hr == S_OK)
+        {
+            const WCHAR *str;
+            WCHAR *str_exp;
+            UINT len;
+
+            ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml);
+
+            len = 1;
+            str = NULL;
+            hr = IXmlReader_GetLocalName(reader, &str, &len);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(len == strlen(test->name), "got %u\n", len);
+            str_exp = a2w(test->name);
+            ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+            free_str(str_exp);
+
+            len = 1;
+            str = NULL;
+            hr = IXmlReader_GetQualifiedName(reader, &str, &len);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(len == strlen(test->name), "got %u\n", len);
+            str_exp = a2w(test->name);
+            ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+            free_str(str_exp);
+
+            /* value */
+            len = 1;
+            str = NULL;
+            hr = IXmlReader_GetValue(reader, &str, &len);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(len == strlen(test->value), "got %u\n", len);
+            str_exp = a2w(test->value);
+            ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+            free_str(str_exp);
+        }
+
+        IStream_Release(stream);
+        test++;
+    }
+
+    IXmlReader_Release(reader);
+}
+
 START_TEST(reader)
 {
     HRESULT r;
@@ -1334,6 +1416,7 @@ START_TEST(reader)
     test_reader_create();
     test_readerinput();
     test_reader_state();
+    test_read_cdata();
     test_read_comment();
     test_read_pi();
     test_read_dtd();




More information about the wine-cvs mailing list