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é" />
245 /// <p:foo xmlns:p="http://example.org/rosé" />
246 /// <p:foo xmlns:p="http://example.org/rosé" />
247 /// <p:foo xmlns:p="http://example.org/rosé" />
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}