[PATCH 1/2] xmllite/reader: Implement MoveToAttributeByName()
Nikolay Sivov
nsivov at codeweavers.com
Fri Jul 21 06:26:43 CDT 2017
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/xmllite/reader.c | 185 ++++++++++++++++++++++++++++----------------
dlls/xmllite/tests/reader.c | 85 ++++++++++++++++++++
2 files changed, 204 insertions(+), 66 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 7f127f614f..0a3d21cb1d 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -521,6 +521,19 @@ static void reader_clear_elements(xmlreader *reader)
reader->is_empty_element = FALSE;
}
+static struct ns *reader_lookup_ns(xmlreader *reader, const strval *prefix)
+{
+ struct list *nslist = prefix ? &reader->ns : &reader->nsdef;
+ struct ns *ns;
+
+ LIST_FOR_EACH_ENTRY_REV(ns, nslist, struct ns, entry) {
+ if (strval_eq(reader, prefix, &ns->prefix))
+ return ns;
+ }
+
+ return NULL;
+}
+
static HRESULT reader_inc_depth(xmlreader *reader)
{
return (++reader->depth >= reader->max_depth && reader->max_depth) ? SC_E_MAXELEMENTDEPTH : S_OK;
@@ -2989,12 +3002,110 @@ static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader* iface)
return next ? S_OK : S_FALSE;
}
+static void reader_get_attribute_ns_uri(xmlreader *reader, struct attribute *attr, const WCHAR **uri, UINT *len)
+{
+ static const WCHAR xmlns_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
+ '2','0','0','0','/','x','m','l','n','s','/',0};
+ static const WCHAR xml_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
+ 'X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
+
+ /* Check for reserved prefixes first */
+ if ((strval_eq(reader, &attr->prefix, &strval_empty) && strval_eq(reader, &attr->localname, &strval_xmlns)) ||
+ strval_eq(reader, &attr->prefix, &strval_xmlns))
+ {
+ *uri = xmlns_uriW;
+ *len = sizeof(xmlns_uriW)/sizeof(xmlns_uriW[0]) - 1;
+ }
+ else if (strval_eq(reader, &attr->prefix, &strval_xml))
+ {
+ *uri = xml_uriW;
+ *len = sizeof(xml_uriW)/sizeof(xml_uriW[0]) - 1;
+ }
+ else
+ {
+ *uri = NULL;
+ *len = 0;
+ }
+
+ if (!*uri)
+ {
+ struct ns *ns;
+
+ if ((ns = reader_lookup_ns(reader, &attr->prefix)))
+ {
+ *uri = ns->uri.str;
+ *len = ns->uri.len;
+ }
+ else
+ {
+ *uri = emptyW;
+ *len = 0;
+ }
+ }
+}
+
+static void reader_get_attribute_local_name(xmlreader *reader, struct attribute *attr, const WCHAR **name, UINT *len)
+{
+ if (attr->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION)
+ {
+ *name = xmlnsW;
+ *len = 5;
+ }
+ else if (attr->flags & ATTRIBUTE_NS_DEFINITION)
+ {
+ const struct ns *ns = reader_lookup_ns(reader, &attr->localname);
+ *name = ns->prefix.str;
+ *len = ns->prefix.len;
+ }
+ else
+ {
+ *name = attr->localname.str;
+ *len = attr->localname.len;
+ }
+}
+
static HRESULT WINAPI xmlreader_MoveToAttributeByName(IXmlReader* iface,
- LPCWSTR local_name,
- LPCWSTR namespaceUri)
+ const WCHAR *local_name, const WCHAR *namespace_uri)
{
- FIXME("(%p %p %p): stub\n", iface, local_name, namespaceUri);
- return E_NOTIMPL;
+ xmlreader *This = impl_from_IXmlReader(iface);
+ UINT target_name_len, target_uri_len;
+ struct attribute *attr;
+
+ TRACE("(%p)->(%s %s)\n", This, debugstr_w(local_name), debugstr_w(namespace_uri));
+
+ if (!local_name)
+ return E_INVALIDARG;
+
+ if (!This->attr_count)
+ return S_FALSE;
+
+ if (!namespace_uri)
+ namespace_uri = emptyW;
+
+ target_name_len = strlenW(local_name);
+ target_uri_len = strlenW(namespace_uri);
+
+ LIST_FOR_EACH_ENTRY(attr, &This->attrs, struct attribute, entry)
+ {
+ UINT name_len, uri_len;
+ const WCHAR *name, *uri;
+
+ reader_get_attribute_local_name(This, attr, &name, &name_len);
+ reader_get_attribute_ns_uri(This, attr, &uri, &uri_len);
+
+ if (name_len == target_name_len && uri_len == target_uri_len &&
+ !strcmpW(name, local_name) && !strcmpW(uri, namespace_uri))
+ {
+ This->attr = attr;
+ This->chunk_read_off = 0;
+ reader_set_strvalue(This, StringValue_Prefix, &This->attr->prefix);
+ reader_set_strvalue(This, StringValue_QualifiedName, &This->attr->qname);
+ reader_set_strvalue(This, StringValue_Value, &This->attr->value);
+ return S_OK;
+ }
+ }
+
+ return S_FALSE;
}
static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
@@ -3088,19 +3199,6 @@ static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *nam
return S_OK;
}
-static struct ns *reader_lookup_ns(xmlreader *reader, const strval *prefix)
-{
- struct list *nslist = prefix ? &reader->ns : &reader->nsdef;
- struct ns *ns;
-
- LIST_FOR_EACH_ENTRY_REV(ns, nslist, struct ns, entry) {
- if (strval_eq(reader, prefix, &ns->prefix))
- return ns;
- }
-
- return NULL;
-}
-
static struct ns *reader_lookup_nsdef(xmlreader *reader)
{
if (list_empty(&reader->nsdef))
@@ -3122,42 +3220,10 @@ static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface, const WCHAR *
if (!len)
len = &length;
- *uri = NULL;
- *len = 0;
-
switch ((nodetype = reader_get_nodetype(This)))
{
case XmlNodeType_Attribute:
- {
- static const WCHAR xmlns_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
- '2','0','0','0','/','x','m','l','n','s','/',0};
- static const WCHAR xml_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
- 'X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
-
- /* check for reserved prefixes first */
- if ((strval_eq(This, prefix, &strval_empty) && strval_eq(This, &This->attr->localname, &strval_xmlns)) ||
- strval_eq(This, prefix, &strval_xmlns))
- {
- *uri = xmlns_uriW;
- *len = sizeof(xmlns_uriW)/sizeof(xmlns_uriW[0]) - 1;
- }
- else if (strval_eq(This, prefix, &strval_xml)) {
- *uri = xml_uriW;
- *len = sizeof(xml_uriW)/sizeof(xml_uriW[0]) - 1;
- }
-
- if (!*uri) {
- ns = reader_lookup_ns(This, prefix);
- if (ns) {
- *uri = ns->uri.str;
- *len = ns->uri.len;
- }
- else {
- *uri = emptyW;
- *len = 0;
- }
- }
- }
+ reader_get_attribute_ns_uri(This, This->attr, uri, len);
break;
case XmlNodeType_Element:
case XmlNodeType_EndElement:
@@ -3189,6 +3255,8 @@ static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface, const WCHAR *
break;
default:
FIXME("Unhandled node type %d\n", nodetype);
+ *uri = NULL;
+ *len = 0;
return E_NOTIMPL;
}
@@ -3222,22 +3290,7 @@ static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface, LPCWSTR *name, U
*len = element->localname.len;
break;
case XmlNodeType_Attribute:
- if (This->attr->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION)
- {
- *name = xmlnsW;
- *len = 5;
- }
- else if (This->attr->flags & ATTRIBUTE_NS_DEFINITION)
- {
- const struct ns *ns = reader_lookup_ns(This, &This->attr->localname);
- *name = ns->prefix.str;
- *len = ns->prefix.len;
- }
- else
- {
- *name = This->attr->localname.str;
- *len = This->attr->localname.len;
- }
+ reader_get_attribute_local_name(This, This->attr, name, len);
break;
default:
*name = This->strvalues[StringValue_LocalName].str;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 673e6c409c..3ae9283be7 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -2571,6 +2571,90 @@ static void test_string_pointers(void)
IXmlReader_Release(reader);
}
+static void test_attribute_by_name(void)
+{
+ static const char *xml = "<a><elem xmlns=\"myns\" a=\"value a\" b=\"value b\" xmlns:ns=\"ns uri\" "
+ "ns:c=\"value c\" c=\"value c2\"/></a>";
+ static const WCHAR xmlns_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
+ '2','0','0','0','/','x','m','l','n','s','/',0};
+ static const WCHAR nsuriW[] = {'n','s',' ','u','r','i',0};
+ static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
+ static const WCHAR mynsW[] = {'m','y','n','s',0};
+ static const WCHAR nsW[] = {'n','s',0};
+ static const WCHAR emptyW[] = {0};
+ static const WCHAR aW[] = {'a',0};
+ static const WCHAR bW[] = {'b',0};
+ static const WCHAR cW[] = {'c',0};
+ IXmlReader *reader;
+ HRESULT hr;
+
+ hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
+ ok(hr == S_OK, "Failed to create reader, hr %#x.\n", hr);
+
+ set_input_string(reader, xml);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, emptyW, NULL);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ read_node(reader, XmlNodeType_Element);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, emptyW, NULL);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ read_node(reader, XmlNodeType_Element);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, NULL, xmlns_uriW);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, emptyW, xmlns_uriW);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, xmlnsW, NULL);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, xmlnsW, xmlns_uriW);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "myns");
+
+ hr = IXmlReader_MoveToAttributeByName(reader, aW, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "value a");
+
+ hr = IXmlReader_MoveToAttributeByName(reader, bW, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "value b");
+
+ hr = IXmlReader_MoveToAttributeByName(reader, aW, mynsW);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, nsW, NULL);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IXmlReader_MoveToAttributeByName(reader, nsW, xmlns_uriW);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "ns uri");
+
+ hr = IXmlReader_MoveToAttributeByName(reader, bW, emptyW);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "value b");
+
+ hr = IXmlReader_MoveToAttributeByName(reader, cW, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "value c2");
+
+ hr = IXmlReader_MoveToAttributeByName(reader, cW, nsuriW);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ reader_value(reader, "value c");
+
+ IXmlReader_Release(reader);
+}
+
START_TEST(reader)
{
test_reader_create();
@@ -2598,4 +2682,5 @@ START_TEST(reader)
test_max_element_depth();
test_reader_position();
test_string_pointers();
+ test_attribute_by_name();
}
--
2.13.2
More information about the wine-patches
mailing list