Repository: tafia/quick-xml (rust)

Issue:
resolve_namespace method does not support default namespace
The `resolve_namespace` method does not seems to resolve the default namespace (with the `xmlns="foo"` syntax) even if `read_namespaced_event` works property.

Here is a modified test case to highlight the problem: 

```rust
#[test]
fn test_default_namespace() {
    let mut r = Reader::from_str("<a ><b xmlns=\"www1\"></b></a>");
    r.trim_text(true);


    // <a>
    let mut buf = Vec::new();
    let mut ns_buf = Vec::new();
    if let Ok((None, Start(_))) = r.read_namespaced_event(&mut buf, &mut ns_buf) {
    } else {
        assert!(false, "expecting outer start element with no namespace");
    }

    // <b>
    if let Ok((Some(a), Start(event))) = r.read_namespaced_event(&mut buf, &mut ns_buf) {
        if &*a == b"www1" {
            assert!(true);
        } else {
            assert!(false, "expecting namespace to resolve to 'www1'");
        }

        //We check if the resolve_namespace method also work properly
        if let (Some(a), _) = r.resolve_namespace(event.name(), &mut Vec::default()) {
            if &*a == b"www1" {
                assert!(true);
            } else {
                assert!(false, "expecting namespace to resolve to 'www1'");
            }
        } else {
            assert!(false, "expecting namespace resolution by the resolve_nemespace method");
        }
    } else {
        assert!(false, "expecting namespace resolution");
    }


    // </b>
    if let Ok((Some(a), End(_))) = r.read_namespaced_event(&mut buf, &mut ns_buf) {
        if &*a == b"www1" {
            assert!(true);
        } else {
            assert!(false, "expecting namespace to resolve to 'www1'");
        }
    } else {
        assert!(false, "expecting namespace resolution");
    }

    // </a> very important: a should not be in any namespace. The default namespace only applies to
    // the sub-document it is defined on.
    if let Ok((None, End(_))) = r.read_namespaced_event(&mut buf, &mut ns_buf) {
    } else {
        assert!(false, "expecting outer end element with no namespace");
    }
}
```


Pull request:
rename resolve_namespace into attribute_namespace
Close #136

Change fn name in order to convey the fact that the namespace resolution is done for attributes only. Adds a event specific function on top of it (probably not used much).

This is a breaking change.


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index d38f6eb..ad78ea6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "quick-xml"
-version = "0.12.4"
+version = "0.13.0"
 authors = ["Johann Tuffe <tafia973@gmail.com>"]
 description = "High performance xml reader and writer"
 
diff --git a/Changelog.md b/Changelog.md
index 81648e0..800f8ae 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -8,11 +8,15 @@
   - test: Adding missing tests
   - chore: Changes to the build process or auxiliary tools/libraries/documentation
 
+## 0.13.0
+- feat: rename `resolve_namespace` into `attribute_namespace`
+- feat: add a `event_namespace` fn
+
 ## 0.12.4
 - fix: Fix minor bug for parsing comment tag
 
 ## 0.12.3
-- feat: add BytesStart::{owned_name, borrowed_name} 
+- feat: add `BytesStart::{owned_name, borrowed_name}`
 
 ## 0.12.2
 - refactor: bump dependencies
diff --git a/src/reader.rs b/src/reader.rs
index 8ab3149..ce5c0d5 100644
--- a/src/reader.rs
+++ b/src/reader.rs
@@ -496,6 +496,23 @@ impl<B: BufRead> Reader<B> {
         event
     }
 
+    /// Resolves a potentially qualified **event name** into (namespace name, local name).
+    ///
+    /// *Qualified* attribute names have the form `prefix:local-name` where the`prefix` is defined
+    /// on any containing XML element via `xmlns:prefix="the:namespace:uri"`. The namespace prefix
+    /// can be defined on the same element as the attribute in question.
+    ///
+    /// *Unqualified* event inherits the current *default namespace*.
+    #[inline]
+    pub fn event_namespace<'a, 'b, 'c>(
+        &'a self,
+        qname: &'b [u8],
+        namespace_buffer: &'c [u8],
+    ) -> (Option<&'c [u8]>, &'b [u8]) {
+        self.ns_buffer
+            .resolve_namespace(qname, namespace_buffer, true)
+    }
+
     /// Resolves a potentially qualified **attribute name** into (namespace name, local name).
     ///
     /// *Qualified* attribute names have the form `prefix:local-name` where the`prefix` is defined
@@ -504,12 +521,13 @@ impl<B: BufRead> Reader<B> {
     ///
     /// *Unqualified* attribute names do *not* inherit the current *default namespace*.
     #[inline]
-    pub fn resolve_namespace<'a, 'b, 'c>(
+    pub fn attribute_namespace<'a, 'b, 'c>(
         &'a self,
         qname: &'b [u8],
         namespace_buffer: &'c [u8],
     ) -> (Option<&'c [u8]>, &'b [u8]) {
-        self.ns_buffer.resolve_namespace(qname, namespace_buffer)
+        self.ns_buffer
+            .resolve_namespace(qname, namespace_buffer, false)
     }
 
     /// Reads the next event and resolves its namespace (if applicable).
@@ -982,15 +1000,31 @@ impl NamespaceBufferIndex {
         &'a self,
         qname: &'b [u8],
         buffer: &'c [u8],
+        use_default: bool,
     ) -> (Option<&'c [u8]>, &'b [u8]) {
-        memchr::memchr(b':', qname)
-            .and_then(|len| {
+        match memchr::memchr(b':', qname) {
+            Some(len) => {
                 let (prefix, value) = qname.split_at(len);
-                self.slices
+                let ns = self
+                    .slices
                     .iter()
                     .rev()
                     .find(|n| n.prefix(buffer) == prefix)
-                    .map(|ns| (ns.opt_value(buffer), &value[1..]))
-            }).unwrap_or((None, qname))
+                    .and_then(|ns| ns.opt_value(buffer));
+                (ns, &value[1..])
+            }
+            None => {
+                let ns = if use_default {
+                    self.slices
+                        .iter()
+                        .rev()
+                        .find(|n| n.prefix_len == 0)
+                        .and_then(|ns| ns.opt_value(buffer))
+                } else {
+                    None
+                };
+                (ns, qname)
+            }
+        }
     }
 }


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index 3713735..a8dae4e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -118,7 +118,7 @@ fn test_attributes_empty_ns() {
             // we don't care about xmlns attributes for this test
             .filter(|kv| !kv.key.starts_with(b"xmlns"))
             .map(|Attribute { key: name, value }| {
-                let (opt_ns, local_name) = r.resolve_namespace(name, &ns_buf);
+                let (opt_ns, local_name) = r.attribute_namespace(name, &ns_buf);
                 (opt_ns, local_name, value)
             });
     match atts.next() {
@@ -162,7 +162,7 @@ fn test_attributes_empty_ns_expanded() {
             // we don't care about xmlns attributes for this test
             .filter(|kv| !kv.key.starts_with(b"xmlns"))
             .map(|Attribute { key: name, value }| {
-                let (opt_ns, local_name) = r.resolve_namespace(name, &ns_buf);
+                let (opt_ns, local_name) = r.attribute_namespace(name, &ns_buf);
                 (opt_ns, local_name, value)
             });
         match atts.next() {
@@ -226,7 +226,7 @@ fn test_default_ns_shadowing_empty() {
             // we don't care about xmlns attributes for this test
             .filter(|kv| !kv.key.starts_with(b"xmlns"))
             .map(|Attribute { key: name, value }| {
-                let (opt_ns, local_name) = r.resolve_namespace(name, &ns_buf);
+                let (opt_ns, local_name) = r.attribute_namespace(name, &ns_buf);
                 (opt_ns, local_name, value)
             });
         // the attribute should _not_ have a namespace name. The default namespace does not
@@ -287,7 +287,7 @@ fn test_default_ns_shadowing_expanded() {
             // we don't care about xmlns attributes for this test
             .filter(|kv| !kv.key.starts_with(b"xmlns"))
             .map(|Attribute { key: name, value }| {
-                let (opt_ns, local_name) = r.resolve_namespace(name, &ns_buf);
+                let (opt_ns, local_name) = r.attribute_namespace(name, &ns_buf);
                 (opt_ns, local_name, value)
             });
         // the attribute should _not_ have a namespace name. The default namespace does not
@@ -401,3 +401,50 @@ fn fuzz_101() {
         buf.clear();
     }
 }
+
+#[test]
+fn test_default_namespace() {
+    let mut r = Reader::from_str("<a ><b xmlns=\"www1\"></b></a>");
+    r.trim_text(true);
+
+    // <a>
+    let mut buf = Vec::new();
+    let mut ns_buf = Vec::new();
+    if let Ok((None, Start(_))) = r.read_namespaced_event(&mut buf, &mut ns_buf) {
+    } else {
+        panic!("expecting outer start element with no namespace");
+    }
+
+    // <b>
+    {
+        let event = match r.read_namespaced_event(&mut buf, &mut ns_buf) {
+            Ok((Some(b"www1"), Start(event))) => event,
+            Ok((Some(_), Start(_))) => panic!("expecting namespace to resolve to 'www1'"),
+            _ => panic!("expecting namespace resolution"),
+        };
+
+        //We check if the resolve_namespace method also work properly
+        match r.event_namespace(event.name(), &mut ns_buf) {
+            (Some(b"www1"), _) => (),
+            (Some(_), _) => panic!("expecting namespace to resolve to 'www1'"),
+            ns => panic!(
+                "expecting namespace resolution by the resolve_nemespace method {:?}",
+                ns
+            ),
+        }
+    }
+
+    // </b>
+    match r.read_namespaced_event(&mut buf, &mut ns_buf) {
+        Ok((Some(b"www1"), End(_))) => (),
+        Ok((Some(_), End(_))) => panic!("expecting namespace to resolve to 'www1'"),
+        _ => panic!("expecting namespace resolution"),
+    }
+
+    // </a> very important: a should not be in any namespace. The default namespace only applies to
+    // the sub-document it is defined on.
+    if let Ok((None, End(_))) = r.read_namespaced_event(&mut buf, &mut ns_buf) {
+    } else {
+        panic!("expecting outer end element with no namespace");
+    }
+}