quick_xml/
name.rs

1//! Module for handling names according to the W3C [Namespaces in XML 1.1 (Second Edition)][spec]
2//! specification
3//!
4//! [spec]: https://www.w3.org/TR/xml-names11
5
6use crate::errors::{Error, Result};
7use crate::events::attributes::Attribute;
8use crate::events::BytesStart;
9use crate::utils::write_byte_string;
10use memchr::memchr;
11use std::convert::TryFrom;
12use std::fmt::{self, Debug, Formatter};
13
14/// A [qualified name] of an element or an attribute, including an optional
15/// namespace [prefix](Prefix) and a [local name](LocalName).
16///
17/// [qualified name]: https://www.w3.org/TR/xml-names11/#dt-qualname
18#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
20pub struct QName<'a>(pub &'a [u8]);
21impl<'a> QName<'a> {
22    /// Converts this name to an internal slice representation.
23    #[inline(always)]
24    pub fn into_inner(self) -> &'a [u8] {
25        self.0
26    }
27
28    /// Returns local part of this qualified name.
29    ///
30    /// All content up to and including the first `:` character is removed from
31    /// the tag name.
32    ///
33    /// # Examples
34    ///
35    /// ```
36    /// # use quick_xml::name::QName;
37    /// let simple = QName(b"simple-name");
38    /// assert_eq!(simple.local_name().as_ref(), b"simple-name");
39    ///
40    /// let qname = QName(b"namespace:simple-name");
41    /// assert_eq!(qname.local_name().as_ref(), b"simple-name");
42    /// ```
43    pub fn local_name(&self) -> LocalName<'a> {
44        LocalName(self.index().map_or(self.0, |i| &self.0[i + 1..]))
45    }
46
47    /// Returns namespace part of this qualified name or `None` if namespace part
48    /// is not defined (symbol `':'` not found).
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// # use std::convert::AsRef;
54    /// # use quick_xml::name::QName;
55    /// let simple = QName(b"simple-name");
56    /// assert_eq!(simple.prefix(), None);
57    ///
58    /// let qname = QName(b"prefix:simple-name");
59    /// assert_eq!(qname.prefix().as_ref().map(|n| n.as_ref()), Some(b"prefix".as_ref()));
60    /// ```
61    pub fn prefix(&self) -> Option<Prefix<'a>> {
62        self.index().map(|i| Prefix(&self.0[..i]))
63    }
64
65    /// The same as `(qname.local_name(), qname.prefix())`, but does only one
66    /// lookup for a `':'` symbol.
67    pub fn decompose(&self) -> (LocalName<'a>, Option<Prefix<'a>>) {
68        match self.index() {
69            None => (LocalName(self.0), None),
70            Some(i) => (LocalName(&self.0[i + 1..]), Some(Prefix(&self.0[..i]))),
71        }
72    }
73
74    /// If that `QName` represents `"xmlns"` series of names, returns `Some`,
75    /// otherwise `None` is returned.
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// # use quick_xml::name::{QName, PrefixDeclaration};
81    /// let qname = QName(b"xmlns");
82    /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Default));
83    ///
84    /// let qname = QName(b"xmlns:prefix");
85    /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"prefix")));
86    ///
87    /// // Be aware that this method does not check the validity of the prefix - it can be empty!
88    /// let qname = QName(b"xmlns:");
89    /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"")));
90    ///
91    /// let qname = QName(b"other-name");
92    /// assert_eq!(qname.as_namespace_binding(), None);
93    ///
94    /// // https://www.w3.org/TR/xml-names11/#xmlReserved
95    /// let qname = QName(b"xmlns-reserved-name");
96    /// assert_eq!(qname.as_namespace_binding(), None);
97    /// ```
98    pub fn as_namespace_binding(&self) -> Option<PrefixDeclaration<'a>> {
99        if self.0.starts_with(b"xmlns") {
100            return match self.0.get(5) {
101                None => Some(PrefixDeclaration::Default),
102                Some(&b':') => Some(PrefixDeclaration::Named(&self.0[6..])),
103                _ => None,
104            };
105        }
106        None
107    }
108
109    /// Returns the index in the name where prefix ended
110    #[inline(always)]
111    fn index(&self) -> Option<usize> {
112        memchr(b':', self.0)
113    }
114}
115impl<'a> Debug for QName<'a> {
116    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
117        write!(f, "QName(")?;
118        write_byte_string(f, self.0)?;
119        write!(f, ")")
120    }
121}
122impl<'a> AsRef<[u8]> for QName<'a> {
123    #[inline]
124    fn as_ref(&self) -> &[u8] {
125        self.0
126    }
127}
128
129////////////////////////////////////////////////////////////////////////////////////////////////////
130
131/// A [local (unqualified) name] of an element or an attribute, i.e. a name
132/// without [prefix](Prefix).
133///
134/// [local (unqualified) name]: https://www.w3.org/TR/xml-names11/#dt-localname
135#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
136#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
137pub struct LocalName<'a>(&'a [u8]);
138impl<'a> LocalName<'a> {
139    /// Converts this name to an internal slice representation.
140    #[inline(always)]
141    pub fn into_inner(self) -> &'a [u8] {
142        self.0
143    }
144}
145impl<'a> Debug for LocalName<'a> {
146    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
147        write!(f, "LocalName(")?;
148        write_byte_string(f, self.0)?;
149        write!(f, ")")
150    }
151}
152impl<'a> AsRef<[u8]> for LocalName<'a> {
153    #[inline]
154    fn as_ref(&self) -> &[u8] {
155        self.0
156    }
157}
158impl<'a> From<QName<'a>> for LocalName<'a> {
159    /// Creates `LocalName` from a [`QName`]
160    ///
161    /// # Examples
162    ///
163    /// ```
164    /// # use quick_xml::name::{LocalName, QName};
165    ///
166    /// let local: LocalName = QName(b"unprefixed").into();
167    /// assert_eq!(local.as_ref(), b"unprefixed");
168    ///
169    /// let local: LocalName = QName(b"some:prefix").into();
170    /// assert_eq!(local.as_ref(), b"prefix");
171    /// ```
172    #[inline]
173    fn from(name: QName<'a>) -> Self {
174        Self(name.index().map_or(name.0, |i| &name.0[i + 1..]))
175    }
176}
177
178////////////////////////////////////////////////////////////////////////////////////////////////////
179
180/// A [namespace prefix] part of the [qualified name](QName) of an element tag
181/// or an attribute: a `prefix` in `<prefix:local-element-name>` or
182/// `prefix:local-attribute-name="attribute value"`.
183///
184/// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix
185#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
186#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
187pub struct Prefix<'a>(&'a [u8]);
188impl<'a> Prefix<'a> {
189    /// Extracts internal slice
190    #[inline(always)]
191    pub fn into_inner(self) -> &'a [u8] {
192        self.0
193    }
194}
195impl<'a> Debug for Prefix<'a> {
196    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
197        write!(f, "Prefix(")?;
198        write_byte_string(f, self.0)?;
199        write!(f, ")")
200    }
201}
202impl<'a> AsRef<[u8]> for Prefix<'a> {
203    #[inline]
204    fn as_ref(&self) -> &[u8] {
205        self.0
206    }
207}
208
209////////////////////////////////////////////////////////////////////////////////////////////////////
210
211/// A namespace prefix declaration, `xmlns` or `xmlns:<name>`, as defined in
212/// [XML Schema specification](https://www.w3.org/TR/xml-names11/#ns-decl)
213#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
214pub enum PrefixDeclaration<'a> {
215    /// XML attribute binds a default namespace. Corresponds to `xmlns` in `xmlns="..."`
216    Default,
217    /// XML attribute binds a specified prefix to a namespace. Corresponds to a
218    /// `prefix` in `xmlns:prefix="..."`, which is stored as payload of this variant.
219    Named(&'a [u8]),
220}
221
222////////////////////////////////////////////////////////////////////////////////////////////////////
223
224/// A [namespace name] that is declared in a `xmlns[:prefix]="namespace name"`.
225///
226/// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
227#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
228#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
229pub struct Namespace<'a>(pub &'a [u8]);
230impl<'a> Namespace<'a> {
231    /// Converts this namespace to an internal slice representation.
232    ///
233    /// This is [non-normalized] attribute value, i.e. any entity references is
234    /// not expanded and space characters are not removed. This means, that
235    /// different byte slices, returned from this method, can represent the same
236    /// namespace and would be treated by parser as identical.
237    ///
238    /// For example, if the entity **eacute** has been defined to be **é**,
239    /// the empty tags below all contain namespace declarations binding the
240    /// prefix `p` to the same [IRI reference], `http://example.org/rosé`.
241    ///
242    /// ```xml
243    /// <p:foo xmlns:p="http://example.org/rosé" />
244    /// <p:foo xmlns:p="http://example.org/ros&#xe9;" />
245    /// <p:foo xmlns:p="http://example.org/ros&#xE9;" />
246    /// <p:foo xmlns:p="http://example.org/ros&#233;" />
247    /// <p:foo xmlns:p="http://example.org/ros&eacute;" />
248    /// ```
249    ///
250    /// This is because XML entity references are expanded during attribute value
251    /// normalization.
252    ///
253    /// [non-normalized]: https://www.w3.org/TR/xml11/#AVNormalize
254    /// [IRI reference]: https://datatracker.ietf.org/doc/html/rfc3987
255    #[inline(always)]
256    pub fn into_inner(self) -> &'a [u8] {
257        self.0
258    }
259    //TODO: implement value normalization and use it when comparing namespaces
260}
261impl<'a> Debug for Namespace<'a> {
262    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
263        write!(f, "Namespace(")?;
264        write_byte_string(f, self.0)?;
265        write!(f, ")")
266    }
267}
268impl<'a> AsRef<[u8]> for Namespace<'a> {
269    #[inline]
270    fn as_ref(&self) -> &[u8] {
271        self.0
272    }
273}
274
275////////////////////////////////////////////////////////////////////////////////////////////////////
276
277/// Result of [prefix] resolution which creates by [`NsReader::resolve_attribute`],
278/// [`NsReader::resolve_element`], [`NsReader::read_resolved_event`] and
279/// [`NsReader::read_resolved_event_into`] methods.
280///
281/// [prefix]: Prefix
282/// [`NsReader::resolve_attribute`]: crate::reader::NsReader::resolve_attribute
283/// [`NsReader::resolve_element`]: crate::reader::NsReader::resolve_element
284/// [`NsReader::read_resolved_event`]: crate::reader::NsReader::read_resolved_event
285/// [`NsReader::read_resolved_event_into`]: crate::reader::NsReader::read_resolved_event_into
286#[derive(Clone, PartialEq, Eq, Hash)]
287pub enum ResolveResult<'ns> {
288    /// Qualified name does not contain prefix, and resolver does not define
289    /// default namespace, so name is not bound to any namespace
290    Unbound,
291    /// [`Prefix`] resolved to the specified namespace
292    Bound(Namespace<'ns>),
293    /// Specified prefix was not found in scope
294    Unknown(Vec<u8>),
295}
296impl<'ns> Debug for ResolveResult<'ns> {
297    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
298        match self {
299            Self::Unbound => write!(f, "Unbound"),
300            Self::Bound(ns) => write!(f, "Bound({:?})", ns),
301            Self::Unknown(p) => {
302                write!(f, "Unknown(")?;
303                write_byte_string(f, p)?;
304                write!(f, ")")
305            }
306        }
307    }
308}
309
310impl<'ns> TryFrom<ResolveResult<'ns>> for Option<Namespace<'ns>> {
311    type Error = Error;
312
313    /// Try to convert this result to an optional namespace and returns
314    /// [`Error::UnknownPrefix`] if this result represents unknown prefix
315    fn try_from(result: ResolveResult<'ns>) -> Result<Self> {
316        use ResolveResult::*;
317
318        match result {
319            Unbound => Ok(None),
320            Bound(ns) => Ok(Some(ns)),
321            Unknown(p) => Err(Error::UnknownPrefix(p)),
322        }
323    }
324}
325
326////////////////////////////////////////////////////////////////////////////////////////////////////
327
328/// An entry that contains index into the buffer with namespace bindings.
329///
330/// Defines a mapping from *[namespace prefix]* to *[namespace name]*.
331/// If prefix is empty, defines a *default namespace* binding that applies to
332/// unprefixed element names (unprefixed attribute names do not bind to any
333/// namespace and they processing is dependent on the element in which their
334/// defined).
335///
336/// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix
337/// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
338#[derive(Debug, Clone)]
339struct NamespaceEntry {
340    /// Index of the namespace in the buffer
341    start: usize,
342    /// Length of the prefix
343    /// * if greater than zero, then binds this namespace to the slice
344    ///   `[start..start + prefix_len]` in the buffer.
345    /// * else defines the current default namespace.
346    prefix_len: usize,
347    /// The length of a namespace name (the URI) of this namespace declaration.
348    /// Name started just after prefix and extend for `value_len` bytes.
349    ///
350    /// The XML standard [specifies] that an empty namespace value 'removes' a namespace declaration
351    /// for the extent of its scope. For prefix declarations that's not very interesting, but it is
352    /// vital for default namespace declarations. With `xmlns=""` you can revert back to the default
353    /// behaviour of leaving unqualified element names unqualified.
354    ///
355    /// [specifies]: https://www.w3.org/TR/xml-names11/#scoping
356    value_len: usize,
357    /// Level of nesting at which this namespace was declared. The declaring element is included,
358    /// i.e., a declaration on the document root has `level = 1`.
359    /// This is used to pop the namespace when the element gets closed.
360    level: i32,
361}
362
363impl NamespaceEntry {
364    /// Get the namespace prefix, bound to this namespace declaration, or `None`,
365    /// if this declaration is for default namespace (`xmlns="..."`).
366    #[inline]
367    fn prefix<'b>(&self, ns_buffer: &'b [u8]) -> Option<Prefix<'b>> {
368        if self.prefix_len == 0 {
369            None
370        } else {
371            Some(Prefix(&ns_buffer[self.start..self.start + self.prefix_len]))
372        }
373    }
374
375    /// Gets the namespace name (the URI) slice out of namespace buffer
376    ///
377    /// Returns `None` if namespace for this prefix was explicitly removed from
378    /// scope, using `xmlns[:prefix]=""`
379    #[inline]
380    fn namespace<'ns>(&self, buffer: &'ns [u8]) -> ResolveResult<'ns> {
381        if self.value_len == 0 {
382            ResolveResult::Unbound
383        } else {
384            let start = self.start + self.prefix_len;
385            ResolveResult::Bound(Namespace(&buffer[start..start + self.value_len]))
386        }
387    }
388}
389
390/// A namespace management buffer.
391///
392/// Holds all internal logic to push/pop namespaces with their levels.
393#[derive(Debug, Default, Clone)]
394pub(crate) struct NamespaceResolver {
395    /// A stack of namespace bindings to prefixes that currently in scope
396    bindings: Vec<NamespaceEntry>,
397    /// The number of open tags at the moment. We need to keep track of this to know which namespace
398    /// declarations to remove when we encounter an `End` event.
399    nesting_level: i32,
400}
401
402impl NamespaceResolver {
403    /// Begins a new scope and add to it all [namespace bindings] that found in
404    /// the specified start element.
405    ///
406    /// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
407    pub fn push(&mut self, start: &BytesStart, buffer: &mut Vec<u8>) {
408        self.nesting_level += 1;
409        let level = self.nesting_level;
410        // adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns'
411        // (default namespace) attribute.
412        for a in start.attributes().with_checks(false) {
413            if let Ok(Attribute { key: k, value: v }) = a {
414                match k.as_namespace_binding() {
415                    Some(PrefixDeclaration::Default) => {
416                        let start = buffer.len();
417                        buffer.extend_from_slice(&v);
418                        self.bindings.push(NamespaceEntry {
419                            start,
420                            prefix_len: 0,
421                            value_len: v.len(),
422                            level,
423                        });
424                    }
425                    Some(PrefixDeclaration::Named(prefix)) => {
426                        let start = buffer.len();
427                        buffer.extend_from_slice(prefix);
428                        buffer.extend_from_slice(&v);
429                        self.bindings.push(NamespaceEntry {
430                            start,
431                            prefix_len: prefix.len(),
432                            value_len: v.len(),
433                            level,
434                        });
435                    }
436                    None => {}
437                }
438            } else {
439                break;
440            }
441        }
442    }
443
444    /// Ends a top-most scope by popping all [namespace binding], that was added by
445    /// last call to [`Self::push()`].
446    ///
447    /// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
448    pub fn pop(&mut self, buffer: &mut Vec<u8>) {
449        self.nesting_level -= 1;
450        let current_level = self.nesting_level;
451        // from the back (most deeply nested scope), look for the first scope that is still valid
452        match self.bindings.iter().rposition(|n| n.level <= current_level) {
453            // none of the namespaces are valid, remove all of them
454            None => {
455                buffer.clear();
456                self.bindings.clear();
457            }
458            // drop all namespaces past the last valid namespace
459            Some(last_valid_pos) => {
460                if let Some(len) = self.bindings.get(last_valid_pos + 1).map(|n| n.start) {
461                    buffer.truncate(len);
462                    self.bindings.truncate(last_valid_pos + 1);
463                }
464            }
465        }
466    }
467
468    /// Resolves a potentially qualified **element name** or **attribute name**
469    /// into (namespace name, local name).
470    ///
471    /// *Qualified* names have the form `prefix:local-name` where the `prefix` is
472    /// defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`.
473    /// The namespace prefix can be defined on the same element as the element or
474    /// attribute in question.
475    ///
476    /// *Unqualified* attribute names do *not* inherit the current *default namespace*.
477    ///
478    /// # Lifetimes
479    ///
480    /// - `'n`: lifetime of an attribute or an element name
481    /// - `'ns`: lifetime of a namespaces buffer, where all found namespaces are stored
482    #[inline]
483    pub fn resolve<'n, 'ns>(
484        &self,
485        name: QName<'n>,
486        buffer: &'ns [u8],
487        use_default: bool,
488    ) -> (ResolveResult<'ns>, LocalName<'n>) {
489        let (local_name, prefix) = name.decompose();
490        (self.resolve_prefix(prefix, buffer, use_default), local_name)
491    }
492
493    /// Finds a [namespace name] for a given qualified **element name**, borrow
494    /// it from the specified buffer.
495    ///
496    /// Returns `None`, if:
497    /// - name is unqualified
498    /// - prefix not found in the current scope
499    /// - prefix was [unbound] using `xmlns:prefix=""`
500    ///
501    /// # Lifetimes
502    ///
503    /// - `'ns`: lifetime of a namespaces buffer, where all found namespaces are stored
504    ///
505    /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
506    /// [unbound]: https://www.w3.org/TR/xml-names11/#scoping
507    #[inline]
508    pub fn find<'ns>(&self, element_name: QName, buffer: &'ns [u8]) -> ResolveResult<'ns> {
509        self.resolve_prefix(element_name.prefix(), buffer, true)
510    }
511
512    fn resolve_prefix<'ns>(
513        &self,
514        prefix: Option<Prefix>,
515        buffer: &'ns [u8],
516        use_default: bool,
517    ) -> ResolveResult<'ns> {
518        self.bindings
519            .iter()
520            // Find the last defined binding that corresponds to the given prefix
521            .rev()
522            .find_map(|n| match (n.prefix(buffer), prefix) {
523                // This is default namespace definition and name has no explicit prefix
524                (None, None) if use_default => Some(n.namespace(buffer)),
525                (None, None) => Some(ResolveResult::Unbound),
526
527                // One part has prefix but other is not -> skip
528                (None, Some(_)) => None,
529                (Some(_), None) => None,
530
531                // Prefixes does not match -> skip
532                (Some(definition), Some(usage)) if definition != usage => None,
533
534                // Prefixes the same, entry defines binding reset (corresponds to `xmlns:p=""`)
535                _ if n.value_len == 0 => Some(Self::maybe_unknown(prefix)),
536                // Prefixes the same, returns corresponding namespace
537                _ => Some(n.namespace(buffer)),
538            })
539            .unwrap_or_else(|| Self::maybe_unknown(prefix))
540    }
541
542    #[inline]
543    fn maybe_unknown(prefix: Option<Prefix>) -> ResolveResult<'static> {
544        match prefix {
545            Some(p) => ResolveResult::Unknown(p.into_inner().to_vec()),
546            None => ResolveResult::Unbound,
547        }
548    }
549}
550
551#[cfg(test)]
552mod namespaces {
553    use super::*;
554    use pretty_assertions::assert_eq;
555    use ResolveResult::*;
556
557    /// Unprefixed attribute names (resolved with `false` flag) never have a namespace
558    /// according to <https://www.w3.org/TR/xml-names11/#defaulting>:
559    ///
560    /// > A default namespace declaration applies to all unprefixed element names
561    /// > within its scope. Default namespace declarations do not apply directly
562    /// > to attribute names; the interpretation of unprefixed attributes is
563    /// > determined by the element on which they appear.
564    mod unprefixed {
565        use super::*;
566        use pretty_assertions::assert_eq;
567
568        /// Basic tests that checks that basic resolver functionality is working
569        #[test]
570        fn basic() {
571            let name = QName(b"simple");
572            let ns = Namespace(b"default");
573
574            let mut resolver = NamespaceResolver::default();
575            let mut buffer = Vec::new();
576
577            resolver.push(
578                &BytesStart::from_content(" xmlns='default'", 0),
579                &mut buffer,
580            );
581            assert_eq!(buffer, b"default");
582
583            // Check that tags without namespaces does not change result
584            resolver.push(&BytesStart::from_content("", 0), &mut buffer);
585            assert_eq!(buffer, b"default");
586            resolver.pop(&mut buffer);
587
588            assert_eq!(buffer, b"default");
589            assert_eq!(
590                resolver.resolve(name, &buffer, true),
591                (Bound(ns), LocalName(b"simple"))
592            );
593            assert_eq!(
594                resolver.resolve(name, &buffer, false),
595                (Unbound, LocalName(b"simple"))
596            );
597            assert_eq!(resolver.find(name, &buffer), Bound(ns));
598        }
599
600        /// Test adding a second level of namespaces, which replaces the previous binding
601        #[test]
602        fn override_namespace() {
603            let name = QName(b"simple");
604            let old_ns = Namespace(b"old");
605            let new_ns = Namespace(b"new");
606
607            let mut resolver = NamespaceResolver::default();
608            let mut buffer = Vec::new();
609
610            resolver.push(&BytesStart::from_content(" xmlns='old'", 0), &mut buffer);
611            resolver.push(&BytesStart::from_content(" xmlns='new'", 0), &mut buffer);
612
613            assert_eq!(buffer, b"oldnew");
614            assert_eq!(
615                resolver.resolve(name, &buffer, true),
616                (Bound(new_ns), LocalName(b"simple"))
617            );
618            assert_eq!(
619                resolver.resolve(name, &buffer, false),
620                (Unbound, LocalName(b"simple"))
621            );
622            assert_eq!(resolver.find(name, &buffer), Bound(new_ns));
623
624            resolver.pop(&mut buffer);
625            assert_eq!(buffer, b"old");
626            assert_eq!(
627                resolver.resolve(name, &buffer, true),
628                (Bound(old_ns), LocalName(b"simple"))
629            );
630            assert_eq!(
631                resolver.resolve(name, &buffer, false),
632                (Unbound, LocalName(b"simple"))
633            );
634            assert_eq!(resolver.find(name, &buffer), Bound(old_ns));
635        }
636
637        /// Test adding a second level of namespaces, which reset the previous binding
638        /// to not bound state by specifying an empty namespace name.
639        ///
640        /// See <https://www.w3.org/TR/xml-names11/#scoping>
641        #[test]
642        fn reset() {
643            let name = QName(b"simple");
644            let old_ns = Namespace(b"old");
645
646            let mut resolver = NamespaceResolver::default();
647            let mut buffer = Vec::new();
648
649            resolver.push(&BytesStart::from_content(" xmlns='old'", 0), &mut buffer);
650            resolver.push(&BytesStart::from_content(" xmlns=''", 0), &mut buffer);
651
652            assert_eq!(buffer, b"old");
653            assert_eq!(
654                resolver.resolve(name, &buffer, true),
655                (Unbound, LocalName(b"simple"))
656            );
657            assert_eq!(
658                resolver.resolve(name, &buffer, false),
659                (Unbound, LocalName(b"simple"))
660            );
661            assert_eq!(resolver.find(name, &buffer), Unbound);
662
663            resolver.pop(&mut buffer);
664            assert_eq!(buffer, b"old");
665            assert_eq!(
666                resolver.resolve(name, &buffer, true),
667                (Bound(old_ns), LocalName(b"simple"))
668            );
669            assert_eq!(
670                resolver.resolve(name, &buffer, false),
671                (Unbound, LocalName(b"simple"))
672            );
673            assert_eq!(resolver.find(name, &buffer), Bound(old_ns));
674        }
675    }
676
677    mod declared_prefix {
678        use super::*;
679        use pretty_assertions::assert_eq;
680
681        /// Basic tests that checks that basic resolver functionality is working
682        #[test]
683        fn basic() {
684            let name = QName(b"p:with-declared-prefix");
685            let ns = Namespace(b"default");
686
687            let mut resolver = NamespaceResolver::default();
688            let mut buffer = Vec::new();
689
690            resolver.push(
691                &BytesStart::from_content(" xmlns:p='default'", 0),
692                &mut buffer,
693            );
694            assert_eq!(buffer, b"pdefault");
695
696            // Check that tags without namespaces does not change result
697            resolver.push(&BytesStart::from_content("", 0), &mut buffer);
698            assert_eq!(buffer, b"pdefault");
699            resolver.pop(&mut buffer);
700
701            assert_eq!(buffer, b"pdefault");
702            assert_eq!(
703                resolver.resolve(name, &buffer, true),
704                (Bound(ns), LocalName(b"with-declared-prefix"))
705            );
706            assert_eq!(
707                resolver.resolve(name, &buffer, false),
708                (Bound(ns), LocalName(b"with-declared-prefix"))
709            );
710            assert_eq!(resolver.find(name, &buffer), Bound(ns));
711        }
712
713        /// Test adding a second level of namespaces, which replaces the previous binding
714        #[test]
715        fn override_namespace() {
716            let name = QName(b"p:with-declared-prefix");
717            let old_ns = Namespace(b"old");
718            let new_ns = Namespace(b"new");
719
720            let mut resolver = NamespaceResolver::default();
721            let mut buffer = Vec::new();
722
723            resolver.push(&BytesStart::from_content(" xmlns:p='old'", 0), &mut buffer);
724            resolver.push(&BytesStart::from_content(" xmlns:p='new'", 0), &mut buffer);
725
726            assert_eq!(buffer, b"poldpnew");
727            assert_eq!(
728                resolver.resolve(name, &buffer, true),
729                (Bound(new_ns), LocalName(b"with-declared-prefix"))
730            );
731            assert_eq!(
732                resolver.resolve(name, &buffer, false),
733                (Bound(new_ns), LocalName(b"with-declared-prefix"))
734            );
735            assert_eq!(resolver.find(name, &buffer), Bound(new_ns));
736
737            resolver.pop(&mut buffer);
738            assert_eq!(buffer, b"pold");
739            assert_eq!(
740                resolver.resolve(name, &buffer, true),
741                (Bound(old_ns), LocalName(b"with-declared-prefix"))
742            );
743            assert_eq!(
744                resolver.resolve(name, &buffer, false),
745                (Bound(old_ns), LocalName(b"with-declared-prefix"))
746            );
747            assert_eq!(resolver.find(name, &buffer), Bound(old_ns));
748        }
749
750        /// Test adding a second level of namespaces, which reset the previous binding
751        /// to not bound state by specifying an empty namespace name.
752        ///
753        /// See <https://www.w3.org/TR/xml-names11/#scoping>
754        #[test]
755        fn reset() {
756            let name = QName(b"p:with-declared-prefix");
757            let old_ns = Namespace(b"old");
758
759            let mut resolver = NamespaceResolver::default();
760            let mut buffer = Vec::new();
761
762            resolver.push(&BytesStart::from_content(" xmlns:p='old'", 0), &mut buffer);
763            resolver.push(&BytesStart::from_content(" xmlns:p=''", 0), &mut buffer);
764
765            assert_eq!(buffer, b"poldp");
766            assert_eq!(
767                resolver.resolve(name, &buffer, true),
768                (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix"))
769            );
770            assert_eq!(
771                resolver.resolve(name, &buffer, false),
772                (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix"))
773            );
774            assert_eq!(resolver.find(name, &buffer), Unknown(b"p".to_vec()));
775
776            resolver.pop(&mut buffer);
777            assert_eq!(buffer, b"pold");
778            assert_eq!(
779                resolver.resolve(name, &buffer, true),
780                (Bound(old_ns), LocalName(b"with-declared-prefix"))
781            );
782            assert_eq!(
783                resolver.resolve(name, &buffer, false),
784                (Bound(old_ns), LocalName(b"with-declared-prefix"))
785            );
786            assert_eq!(resolver.find(name, &buffer), Bound(old_ns));
787        }
788    }
789
790    #[test]
791    fn undeclared_prefix() {
792        let name = QName(b"unknown:prefix");
793
794        let resolver = NamespaceResolver::default();
795        let buffer = Vec::new();
796
797        assert_eq!(buffer, b"");
798        assert_eq!(
799            resolver.resolve(name, &buffer, true),
800            (Unknown(b"unknown".to_vec()), LocalName(b"prefix"))
801        );
802        assert_eq!(
803            resolver.resolve(name, &buffer, false),
804            (Unknown(b"unknown".to_vec()), LocalName(b"prefix"))
805        );
806        assert_eq!(resolver.find(name, &buffer), Unknown(b"unknown".to_vec()));
807    }
808
809    /// Checks how the QName is decomposed to a prefix and a local name
810    #[test]
811    fn prefix_and_local_name() {
812        let name = QName(b"foo:bus");
813        assert_eq!(name.prefix(), Some(Prefix(b"foo")));
814        assert_eq!(name.local_name(), LocalName(b"bus"));
815        assert_eq!(name.decompose(), (LocalName(b"bus"), Some(Prefix(b"foo"))));
816
817        let name = QName(b"foo:");
818        assert_eq!(name.prefix(), Some(Prefix(b"foo")));
819        assert_eq!(name.local_name(), LocalName(b""));
820        assert_eq!(name.decompose(), (LocalName(b""), Some(Prefix(b"foo"))));
821
822        let name = QName(b":foo");
823        assert_eq!(name.prefix(), Some(Prefix(b"")));
824        assert_eq!(name.local_name(), LocalName(b"foo"));
825        assert_eq!(name.decompose(), (LocalName(b"foo"), Some(Prefix(b""))));
826
827        let name = QName(b"foo:bus:baz");
828        assert_eq!(name.prefix(), Some(Prefix(b"foo")));
829        assert_eq!(name.local_name(), LocalName(b"bus:baz"));
830        assert_eq!(
831            name.decompose(),
832            (LocalName(b"bus:baz"), Some(Prefix(b"foo")))
833        );
834    }
835}