diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c index 9216127b10c..6fd0f6917a7 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 '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 9829452d079..7373a696c33 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[] = { + { "", "", " ]]data ", S_OK }, + { "", "", "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();