xmllite: Initial implementation of attribute parsing.

This commit is contained in:
Nikolay Sivov 2013-07-30 14:59:28 +04:00 committed by Alexandre Julliard
parent ccf04d644b
commit 53f72826a2
2 changed files with 199 additions and 28 deletions

View File

@ -1757,37 +1757,129 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc
return S_OK;
}
/* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
[67] Reference ::= EntityRef | CharRef
[68] EntityRef ::= '&' Name ';' */
static HRESULT reader_parse_reference(xmlreader *reader)
{
FIXME("References not supported\n");
return E_NOTIMPL;
}
/* [10 NS] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" */
static HRESULT reader_parse_attvalue(xmlreader *reader, strval *value)
{
WCHAR *ptr, *start;
WCHAR quote;
ptr = reader_get_cur(reader);
/* skip opening quote */
quote = *ptr;
if (quote != '\"' && quote != '\'') return WC_E_QUOTE;
reader_skipn(reader, 1);
start = ptr = reader_get_cur(reader);
while (*ptr)
{
if (*ptr == '<') return WC_E_LESSTHAN;
if (*ptr == quote)
{
/* skip closing quote */
reader_skipn(reader, 1);
break;
}
if (*ptr == '&')
{
HRESULT hr = reader_parse_reference(reader);
if (FAILED(hr)) return hr;
}
else
reader_skipn(reader, 1);
ptr = reader_get_cur(reader);
}
reader_init_strvalue(start, ptr-start, value);
return S_OK;
}
/* [1 NS] NSAttName ::= PrefixedAttName | DefaultAttName
[2 NS] PrefixedAttName ::= 'xmlns:' NCName
[3 NS] DefaultAttName ::= 'xmlns'
[15 NS] Attribute ::= NSAttName Eq AttValue | QName Eq AttValue */
static HRESULT reader_parse_attribute(xmlreader *reader)
{
static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
strval prefix, local, qname, xmlns, value;
HRESULT hr;
hr = reader_parse_qname(reader, &prefix, &local, &qname);
if (FAILED(hr)) return hr;
reader_init_strvalue((WCHAR*)xmlnsW, 5, &xmlns);
if (strval_eq(&prefix, &xmlns))
{
FIXME("namespace definitions not supported\n");
return E_NOTIMPL;
}
if (strval_eq(&qname, &xmlns))
{
FIXME("default namespace definitions not supported\n");
return E_NOTIMPL;
}
hr = reader_parse_eq(reader);
if (FAILED(hr)) return hr;
hr = reader_parse_attvalue(reader, &value);
if (FAILED(hr)) return hr;
TRACE("%s=\"%s\"\n", debugstr_wn(local.str, local.len), debugstr_wn(value.str, value.len));
return reader_add_attr(reader, &local, &value);
}
/* [12 NS] STag ::= '<' QName (S Attribute)* S? '>'
[14 NS] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' */
static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname, int *empty)
{
static const WCHAR endW[] = {'/','>',0};
HRESULT hr;
hr = reader_parse_qname(reader, prefix, local, qname);
if (FAILED(hr)) return hr;
reader_skipspaces(reader);
/* empty element */
if ((*empty = !reader_cmp(reader, endW)))
while (1)
{
/* skip '/>' */
reader_skipn(reader, 2);
reader->empty_element = TRUE;
return S_OK;
static const WCHAR endW[] = {'/','>',0};
reader_skipspaces(reader);
/* empty element */
if ((*empty = !reader_cmp(reader, endW)))
{
/* skip '/>' */
reader_skipn(reader, 2);
reader->empty_element = TRUE;
return S_OK;
}
/* got a start tag */
if (!reader_cmp(reader, gtW))
{
/* skip '>' */
reader_skipn(reader, 1);
return reader_push_element(reader, qname);
}
hr = reader_parse_attribute(reader);
if (FAILED(hr)) return hr;
}
/* got a start tag */
if (!reader_cmp(reader, gtW))
{
/* skip '>' */
reader_skipn(reader, 1);
return reader_push_element(reader, qname);
}
FIXME("only empty elements/start tags without attribute list supported\n");
return E_NOTIMPL;
return S_OK;
}
/* [39] element ::= EmptyElemTag | STag content ETag */
@ -1937,15 +2029,6 @@ static HRESULT reader_parse_cdata(xmlreader *reader)
return S_OK;
}
/* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
[67] Reference ::= EntityRef | CharRef
[68] EntityRef ::= '&' Name ';' */
static HRESULT reader_parse_reference(xmlreader *reader)
{
FIXME("References not supported\n");
return E_NOTIMPL;
}
/* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */
static HRESULT reader_parse_chardata(xmlreader *reader)
{

View File

@ -1566,6 +1566,93 @@ static void test_isemptyelement(void)
IXmlReader_Release(reader);
}
static struct test_entry attributes_tests[] = {
{ "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK },
{ "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK },
{ "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK },
{ "<a attr1=\' \'/>", "attr1", " ", S_OK },
{ "<a attr1=\" \"/>", "attr1", " ", S_OK },
{ "<a attr1=attrvalue/>", NULL, NULL, WC_E_QUOTE },
{ "<a attr1=\"attr<value\"/>", NULL, NULL, WC_E_LESSTHAN },
{ NULL }
};
static void test_read_attribute(void)
{
struct test_entry *test = attributes_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);
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_Element, "got %d for %s\n", type, test->xml);
hr = IXmlReader_MoveToFirstAttribute(reader);
ok(hr == S_OK, "got 0x%08x\n", hr);
len = 1;
str = NULL;
hr = IXmlReader_GetLocalName(reader, &str, &len);
ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine {
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);
todo_wine {
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);
todo_wine {
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;
@ -1582,6 +1669,7 @@ START_TEST(reader)
test_reader_create();
test_readerinput();
test_reader_state();
test_read_attribute();
test_read_cdata();
test_read_comment();
test_read_pi();