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(default:name.0, |i: usize| &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: &Namespace<'_>) => write!(f, "Bound({:?})", ns),
301 Self::Unknown(p: &Vec) => {
302 write!(f, "Unknown(")?;
303 write_byte_string(f, byte_string: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: Namespace<'_>) => Ok(Some(ns)),
321 Unknown(p: Vec) => 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, Clone)]
394pub(crate) struct NamespaceResolver {
395 /// Buffer that contains names of namespace prefixes (the part between `xmlns:`
396 /// and an `=`) and namespace values.
397 buffer: Vec<u8>,
398 /// A stack of namespace bindings to prefixes that currently in scope
399 bindings: Vec<NamespaceEntry>,
400 /// The number of open tags at the moment. We need to keep track of this to know which namespace
401 /// declarations to remove when we encounter an `End` event.
402 nesting_level: i32,
403}
404
405/// That constant define the one of [reserved namespaces] for the xml standard.
406///
407/// The prefix `xml` is by definition bound to the namespace name
408/// `http://www.w3.org/XML/1998/namespace`. It may, but need not, be declared, and must not be
409/// undeclared or bound to any other namespace name. Other prefixes must not be bound to this
410/// namespace name, and it must not be declared as the default namespace.
411///
412/// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
413const RESERVED_NAMESPACE_XML: (Prefix, Namespace) = (
414 Prefix(b"xml"),
415 Namespace(b"http://www.w3.org/XML/1998/namespace"),
416);
417/// That constant define the one of [reserved namespaces] for the xml standard.
418///
419/// The prefix `xmlns` is used only to declare namespace bindings and is by definition bound
420/// to the namespace name `http://www.w3.org/2000/xmlns/`. It must not be declared or
421/// undeclared. Other prefixes must not be bound to this namespace name, and it must not be
422/// declared as the default namespace. Element names must not have the prefix `xmlns`.
423///
424/// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
425const RESERVED_NAMESPACE_XMLNS: (Prefix, Namespace) = (
426 Prefix(b"xmlns"),
427 Namespace(b"http://www.w3.org/2000/xmlns/"),
428);
429
430impl Default for NamespaceResolver {
431 fn default() -> Self {
432 let mut buffer: Vec = Vec::new();
433 let mut bindings: Vec = Vec::new();
434 for ent: &(Prefix<'_>, Namespace<'_>) in &[RESERVED_NAMESPACE_XML, RESERVED_NAMESPACE_XMLNS] {
435 let prefix: &[u8] = ent.0.into_inner();
436 let uri: &[u8] = ent.1.into_inner();
437 bindings.push(NamespaceEntry {
438 start: buffer.len(),
439 prefix_len: prefix.len(),
440 value_len: uri.len(),
441 level: 0,
442 });
443 buffer.extend(iter:prefix);
444 buffer.extend(iter:uri);
445 }
446
447 Self {
448 buffer,
449 bindings,
450 nesting_level: 0,
451 }
452 }
453}
454
455impl NamespaceResolver {
456 /// Begins a new scope and add to it all [namespace bindings] that found in
457 /// the specified start element.
458 ///
459 /// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
460 pub fn push(&mut self, start: &BytesStart) -> Result<()> {
461 self.nesting_level += 1;
462 let level = self.nesting_level;
463 // adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns'
464 // (default namespace) attribute.
465 for a in start.attributes().with_checks(false) {
466 if let Ok(Attribute { key: k, value: v }) = a {
467 match k.as_namespace_binding() {
468 Some(PrefixDeclaration::Default) => {
469 let start = self.buffer.len();
470 self.buffer.extend_from_slice(&v);
471 self.bindings.push(NamespaceEntry {
472 start,
473 prefix_len: 0,
474 value_len: v.len(),
475 level,
476 });
477 }
478 Some(PrefixDeclaration::Named(b"xml")) => {
479 if Namespace(&v) != RESERVED_NAMESPACE_XML.1 {
480 // error, `xml` prefix explicitly set to different value
481 return Err(Error::InvalidPrefixBind {
482 prefix: b"xml".to_vec(),
483 namespace: v.to_vec(),
484 });
485 }
486 // don't add another NamespaceEntry for the `xml` namespace prefix
487 }
488 Some(PrefixDeclaration::Named(b"xmlns")) => {
489 // error, `xmlns` prefix explicitly set
490 return Err(Error::InvalidPrefixBind {
491 prefix: b"xmlns".to_vec(),
492 namespace: v.to_vec(),
493 });
494 }
495 Some(PrefixDeclaration::Named(prefix)) => {
496 let ns = Namespace(&v);
497
498 if ns == RESERVED_NAMESPACE_XML.1 || ns == RESERVED_NAMESPACE_XMLNS.1 {
499 // error, non-`xml` prefix set to xml uri
500 // error, non-`xmlns` prefix set to xmlns uri
501 return Err(Error::InvalidPrefixBind {
502 prefix: prefix.to_vec(),
503 namespace: v.to_vec(),
504 });
505 }
506
507 let start = self.buffer.len();
508 self.buffer.extend_from_slice(prefix);
509 self.buffer.extend_from_slice(&v);
510 self.bindings.push(NamespaceEntry {
511 start,
512 prefix_len: prefix.len(),
513 value_len: v.len(),
514 level,
515 });
516 }
517 None => {}
518 }
519 } else {
520 break;
521 }
522 }
523 Ok(())
524 }
525
526 /// Ends a top-most scope by popping all [namespace binding], that was added by
527 /// last call to [`Self::push()`].
528 ///
529 /// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
530 pub fn pop(&mut self) {
531 self.nesting_level -= 1;
532 let current_level = self.nesting_level;
533 // from the back (most deeply nested scope), look for the first scope that is still valid
534 match self.bindings.iter().rposition(|n| n.level <= current_level) {
535 // none of the namespaces are valid, remove all of them
536 None => {
537 self.buffer.clear();
538 self.bindings.clear();
539 }
540 // drop all namespaces past the last valid namespace
541 Some(last_valid_pos) => {
542 if let Some(len) = self.bindings.get(last_valid_pos + 1).map(|n| n.start) {
543 self.buffer.truncate(len);
544 self.bindings.truncate(last_valid_pos + 1);
545 }
546 }
547 }
548 }
549
550 /// Resolves a potentially qualified **element name** or **attribute name**
551 /// into (namespace name, local name).
552 ///
553 /// *Qualified* names have the form `prefix:local-name` where the `prefix` is
554 /// defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`.
555 /// The namespace prefix can be defined on the same element as the element or
556 /// attribute in question.
557 ///
558 /// *Unqualified* attribute names do *not* inherit the current *default namespace*.
559 ///
560 /// # Lifetimes
561 ///
562 /// - `'n`: lifetime of an attribute or an element name
563 #[inline]
564 pub fn resolve<'n>(
565 &self,
566 name: QName<'n>,
567 use_default: bool,
568 ) -> (ResolveResult, LocalName<'n>) {
569 let (local_name, prefix) = name.decompose();
570 (self.resolve_prefix(prefix, use_default), local_name)
571 }
572
573 /// Finds a [namespace name] for a given qualified **element name**, borrow
574 /// it from the internal buffer.
575 ///
576 /// Returns `None`, if:
577 /// - name is unqualified
578 /// - prefix not found in the current scope
579 /// - prefix was [unbound] using `xmlns:prefix=""`
580 ///
581 /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
582 /// [unbound]: https://www.w3.org/TR/xml-names11/#scoping
583 #[inline]
584 pub fn find(&self, element_name: QName) -> ResolveResult {
585 self.resolve_prefix(element_name.prefix(), true)
586 }
587
588 fn resolve_prefix(&self, prefix: Option<Prefix>, use_default: bool) -> ResolveResult {
589 self.bindings
590 .iter()
591 // Find the last defined binding that corresponds to the given prefix
592 .rev()
593 .find_map(|n| match (n.prefix(&self.buffer), prefix) {
594 // This is default namespace definition and name has no explicit prefix
595 (None, None) if use_default => Some(n.namespace(&self.buffer)),
596 (None, None) => Some(ResolveResult::Unbound),
597
598 // One part has prefix but other is not -> skip
599 (None, Some(_)) => None,
600 (Some(_), None) => None,
601
602 // Prefixes does not match -> skip
603 (Some(definition), Some(usage)) if definition != usage => None,
604
605 // Prefixes the same, entry defines binding reset (corresponds to `xmlns:p=""`)
606 _ if n.value_len == 0 => Some(Self::maybe_unknown(prefix)),
607 // Prefixes the same, returns corresponding namespace
608 _ => Some(n.namespace(&self.buffer)),
609 })
610 .unwrap_or_else(|| Self::maybe_unknown(prefix))
611 }
612
613 #[inline]
614 fn maybe_unknown(prefix: Option<Prefix>) -> ResolveResult<'static> {
615 match prefix {
616 Some(p) => ResolveResult::Unknown(p.into_inner().to_vec()),
617 None => ResolveResult::Unbound,
618 }
619 }
620}
621
622#[cfg(test)]
623mod namespaces {
624 use super::*;
625 use pretty_assertions::assert_eq;
626 use ResolveResult::*;
627
628 /// Unprefixed attribute names (resolved with `false` flag) never have a namespace
629 /// according to <https://www.w3.org/TR/xml-names11/#defaulting>:
630 ///
631 /// > A default namespace declaration applies to all unprefixed element names
632 /// > within its scope. Default namespace declarations do not apply directly
633 /// > to attribute names; the interpretation of unprefixed attributes is
634 /// > determined by the element on which they appear.
635 mod unprefixed {
636 use super::*;
637 use pretty_assertions::assert_eq;
638
639 /// Basic tests that checks that basic resolver functionality is working
640 #[test]
641 fn basic() {
642 let name = QName(b"simple");
643 let ns = Namespace(b"default");
644
645 let mut resolver = NamespaceResolver::default();
646 let s = resolver.buffer.len();
647
648 resolver
649 .push(&BytesStart::from_content(" xmlns='default'", 0))
650 .unwrap();
651 assert_eq!(&resolver.buffer[s..], b"default");
652
653 // Check that tags without namespaces does not change result
654 resolver.push(&BytesStart::from_content("", 0)).unwrap();
655 assert_eq!(&resolver.buffer[s..], b"default");
656 resolver.pop();
657
658 assert_eq!(&resolver.buffer[s..], b"default");
659 assert_eq!(
660 resolver.resolve(name, true),
661 (Bound(ns), LocalName(b"simple"))
662 );
663 assert_eq!(
664 resolver.resolve(name, false),
665 (Unbound, LocalName(b"simple"))
666 );
667 assert_eq!(resolver.find(name), Bound(ns));
668 }
669
670 /// Test adding a second level of namespaces, which replaces the previous binding
671 #[test]
672 fn override_namespace() {
673 let name = QName(b"simple");
674 let old_ns = Namespace(b"old");
675 let new_ns = Namespace(b"new");
676
677 let mut resolver = NamespaceResolver::default();
678 let s = resolver.buffer.len();
679
680 resolver
681 .push(&BytesStart::from_content(" xmlns='old'", 0))
682 .unwrap();
683 resolver
684 .push(&BytesStart::from_content(" xmlns='new'", 0))
685 .unwrap();
686
687 assert_eq!(&resolver.buffer[s..], b"oldnew");
688 assert_eq!(
689 resolver.resolve(name, true),
690 (Bound(new_ns), LocalName(b"simple"))
691 );
692 assert_eq!(
693 resolver.resolve(name, false),
694 (Unbound, LocalName(b"simple"))
695 );
696 assert_eq!(resolver.find(name), Bound(new_ns));
697
698 resolver.pop();
699 assert_eq!(&resolver.buffer[s..], b"old");
700 assert_eq!(
701 resolver.resolve(name, true),
702 (Bound(old_ns), LocalName(b"simple"))
703 );
704 assert_eq!(
705 resolver.resolve(name, false),
706 (Unbound, LocalName(b"simple"))
707 );
708 assert_eq!(resolver.find(name), Bound(old_ns));
709 }
710
711 /// Test adding a second level of namespaces, which reset the previous binding
712 /// to not bound state by specifying an empty namespace name.
713 ///
714 /// See <https://www.w3.org/TR/xml-names11/#scoping>
715 #[test]
716 fn reset() {
717 let name = QName(b"simple");
718 let old_ns = Namespace(b"old");
719
720 let mut resolver = NamespaceResolver::default();
721 let s = resolver.buffer.len();
722
723 resolver
724 .push(&BytesStart::from_content(" xmlns='old'", 0))
725 .unwrap();
726 resolver
727 .push(&BytesStart::from_content(" xmlns=''", 0))
728 .unwrap();
729
730 assert_eq!(&resolver.buffer[s..], b"old");
731 assert_eq!(
732 resolver.resolve(name, true),
733 (Unbound, LocalName(b"simple"))
734 );
735 assert_eq!(
736 resolver.resolve(name, false),
737 (Unbound, LocalName(b"simple"))
738 );
739 assert_eq!(resolver.find(name), Unbound);
740
741 resolver.pop();
742 assert_eq!(&resolver.buffer[s..], b"old");
743 assert_eq!(
744 resolver.resolve(name, true),
745 (Bound(old_ns), LocalName(b"simple"))
746 );
747 assert_eq!(
748 resolver.resolve(name, false),
749 (Unbound, LocalName(b"simple"))
750 );
751 assert_eq!(resolver.find(name), Bound(old_ns));
752 }
753 }
754
755 mod declared_prefix {
756 use super::*;
757 use pretty_assertions::assert_eq;
758
759 /// Basic tests that checks that basic resolver functionality is working
760 #[test]
761 fn basic() {
762 let name = QName(b"p:with-declared-prefix");
763 let ns = Namespace(b"default");
764
765 let mut resolver = NamespaceResolver::default();
766 let s = resolver.buffer.len();
767
768 resolver
769 .push(&BytesStart::from_content(" xmlns:p='default'", 0))
770 .unwrap();
771 assert_eq!(&resolver.buffer[s..], b"pdefault");
772
773 // Check that tags without namespaces does not change result
774 resolver.push(&BytesStart::from_content("", 0)).unwrap();
775 assert_eq!(&resolver.buffer[s..], b"pdefault");
776 resolver.pop();
777
778 assert_eq!(&resolver.buffer[s..], b"pdefault");
779 assert_eq!(
780 resolver.resolve(name, true),
781 (Bound(ns), LocalName(b"with-declared-prefix"))
782 );
783 assert_eq!(
784 resolver.resolve(name, false),
785 (Bound(ns), LocalName(b"with-declared-prefix"))
786 );
787 assert_eq!(resolver.find(name), Bound(ns));
788 }
789
790 /// Test adding a second level of namespaces, which replaces the previous binding
791 #[test]
792 fn override_namespace() {
793 let name = QName(b"p:with-declared-prefix");
794 let old_ns = Namespace(b"old");
795 let new_ns = Namespace(b"new");
796
797 let mut resolver = NamespaceResolver::default();
798 let s = resolver.buffer.len();
799
800 resolver
801 .push(&BytesStart::from_content(" xmlns:p='old'", 0))
802 .unwrap();
803 resolver
804 .push(&BytesStart::from_content(" xmlns:p='new'", 0))
805 .unwrap();
806
807 assert_eq!(&resolver.buffer[s..], b"poldpnew");
808 assert_eq!(
809 resolver.resolve(name, true),
810 (Bound(new_ns), LocalName(b"with-declared-prefix"))
811 );
812 assert_eq!(
813 resolver.resolve(name, false),
814 (Bound(new_ns), LocalName(b"with-declared-prefix"))
815 );
816 assert_eq!(resolver.find(name), Bound(new_ns));
817
818 resolver.pop();
819 assert_eq!(&resolver.buffer[s..], b"pold");
820 assert_eq!(
821 resolver.resolve(name, true),
822 (Bound(old_ns), LocalName(b"with-declared-prefix"))
823 );
824 assert_eq!(
825 resolver.resolve(name, false),
826 (Bound(old_ns), LocalName(b"with-declared-prefix"))
827 );
828 assert_eq!(resolver.find(name), Bound(old_ns));
829 }
830
831 /// Test adding a second level of namespaces, which reset the previous binding
832 /// to not bound state by specifying an empty namespace name.
833 ///
834 /// See <https://www.w3.org/TR/xml-names11/#scoping>
835 #[test]
836 fn reset() {
837 let name = QName(b"p:with-declared-prefix");
838 let old_ns = Namespace(b"old");
839
840 let mut resolver = NamespaceResolver::default();
841 let s = resolver.buffer.len();
842
843 resolver
844 .push(&BytesStart::from_content(" xmlns:p='old'", 0))
845 .unwrap();
846 resolver
847 .push(&BytesStart::from_content(" xmlns:p=''", 0))
848 .unwrap();
849
850 assert_eq!(&resolver.buffer[s..], b"poldp");
851 assert_eq!(
852 resolver.resolve(name, true),
853 (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix"))
854 );
855 assert_eq!(
856 resolver.resolve(name, false),
857 (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix"))
858 );
859 assert_eq!(resolver.find(name), Unknown(b"p".to_vec()));
860
861 resolver.pop();
862 assert_eq!(&resolver.buffer[s..], b"pold");
863 assert_eq!(
864 resolver.resolve(name, true),
865 (Bound(old_ns), LocalName(b"with-declared-prefix"))
866 );
867 assert_eq!(
868 resolver.resolve(name, false),
869 (Bound(old_ns), LocalName(b"with-declared-prefix"))
870 );
871 assert_eq!(resolver.find(name), Bound(old_ns));
872 }
873 }
874
875 /// Tests for `xml` and `xmlns` built-in prefixes.
876 ///
877 /// See <https://www.w3.org/TR/xml-names11/#xmlReserved>
878 mod builtin_prefixes {
879 use super::*;
880
881 mod xml {
882 use super::*;
883 use pretty_assertions::assert_eq;
884
885 /// `xml` prefix are always defined, it is not required to define it explicitly.
886 #[test]
887 fn undeclared() {
888 let name = QName(b"xml:random");
889 let namespace = RESERVED_NAMESPACE_XML.1;
890
891 let resolver = NamespaceResolver::default();
892
893 assert_eq!(
894 resolver.resolve(name, true),
895 (Bound(namespace), LocalName(b"random"))
896 );
897
898 assert_eq!(
899 resolver.resolve(name, false),
900 (Bound(namespace), LocalName(b"random"))
901 );
902 assert_eq!(resolver.find(name), Bound(namespace));
903 }
904
905 /// `xml` prefix can be declared but it must be bound to the value
906 /// `http://www.w3.org/XML/1998/namespace`
907 #[test]
908 fn rebound_to_correct_ns() {
909 let mut resolver = NamespaceResolver::default();
910 let s = resolver.buffer.len();
911 resolver.push(
912 &BytesStart::from_content(
913 " xmlns:xml='http://www.w3.org/XML/1998/namespace'",
914 0,
915 ),
916 ).expect("`xml` prefix should be possible to bound to `http://www.w3.org/XML/1998/namespace`");
917 assert_eq!(&resolver.buffer[s..], b"");
918 }
919
920 /// `xml` prefix cannot be re-declared to another namespace
921 #[test]
922 fn rebound_to_incorrect_ns() {
923 let mut resolver = NamespaceResolver::default();
924 let s = resolver.buffer.len();
925 match resolver.push(&BytesStart::from_content(
926 " xmlns:xml='not_correct_namespace'",
927 0,
928 )) {
929 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
930 assert_eq!(prefix, b"xml");
931 assert_eq!(namespace, b"not_correct_namespace");
932 }
933 x => panic!(
934 "Expected `Error::ReservedNamespaceError`, but found {:?}",
935 x
936 ),
937 }
938 assert_eq!(&resolver.buffer[s..], b"");
939 }
940
941 /// `xml` prefix cannot be unbound
942 #[test]
943 fn unbound() {
944 let mut resolver = NamespaceResolver::default();
945 let s = resolver.buffer.len();
946 match resolver.push(&BytesStart::from_content(" xmlns:xml=''", 0)) {
947 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
948 assert_eq!(prefix, b"xml");
949 assert_eq!(namespace, b"");
950 }
951 x => panic!(
952 "Expected `Error::ReservedNamespaceError`, but found {:?}",
953 x
954 ),
955 }
956 assert_eq!(&resolver.buffer[s..], b"");
957 }
958
959 /// Other prefix cannot be bound to `xml` namespace
960 #[test]
961 fn other_prefix_bound_to_xml_namespace() {
962 let mut resolver = NamespaceResolver::default();
963 let s = resolver.buffer.len();
964 match resolver.push(&BytesStart::from_content(
965 " xmlns:not_xml='http://www.w3.org/XML/1998/namespace'",
966 0,
967 )) {
968 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
969 assert_eq!(prefix, b"not_xml");
970 assert_eq!(namespace, b"http://www.w3.org/XML/1998/namespace");
971 }
972 x => panic!(
973 "Expected `Error::ReservedNamespaceError`, but found {:?}",
974 x
975 ),
976 }
977 assert_eq!(&resolver.buffer[s..], b"");
978 }
979 }
980
981 mod xmlns {
982 use super::*;
983 use pretty_assertions::assert_eq;
984
985 /// `xmlns` prefix are always defined, it is forbidden to define it explicitly
986 #[test]
987 fn undeclared() {
988 let name = QName(b"xmlns:random");
989 let namespace = RESERVED_NAMESPACE_XMLNS.1;
990
991 let resolver = NamespaceResolver::default();
992
993 assert_eq!(
994 resolver.resolve(name, true),
995 (Bound(namespace), LocalName(b"random"))
996 );
997
998 assert_eq!(
999 resolver.resolve(name, false),
1000 (Bound(namespace), LocalName(b"random"))
1001 );
1002 assert_eq!(resolver.find(name), Bound(namespace));
1003 }
1004
1005 /// `xmlns` prefix cannot be re-declared event to its own namespace
1006 #[test]
1007 fn rebound_to_correct_ns() {
1008 let mut resolver = NamespaceResolver::default();
1009 let s = resolver.buffer.len();
1010 match resolver.push(&BytesStart::from_content(
1011 " xmlns:xmlns='http://www.w3.org/2000/xmlns/'",
1012 0,
1013 )) {
1014 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
1015 assert_eq!(prefix, b"xmlns");
1016 assert_eq!(namespace, b"http://www.w3.org/2000/xmlns/");
1017 }
1018 x => panic!(
1019 "Expected `Error::ReservedNamespaceError`, but found {:?}",
1020 x
1021 ),
1022 }
1023 assert_eq!(&resolver.buffer[s..], b"");
1024 }
1025
1026 /// `xmlns` prefix cannot be re-declared
1027 #[test]
1028 fn rebound_to_incorrect_ns() {
1029 let mut resolver = NamespaceResolver::default();
1030 let s = resolver.buffer.len();
1031 match resolver.push(&BytesStart::from_content(
1032 " xmlns:xmlns='not_correct_namespace'",
1033 0,
1034 )) {
1035 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
1036 assert_eq!(prefix, b"xmlns");
1037 assert_eq!(namespace, b"not_correct_namespace");
1038 }
1039 x => panic!(
1040 "Expected `Error::ReservedNamespaceError`, but found {:?}",
1041 x
1042 ),
1043 }
1044 assert_eq!(&resolver.buffer[s..], b"");
1045 }
1046
1047 /// `xmlns` prefix cannot be unbound
1048 #[test]
1049 fn unbound() {
1050 let mut resolver = NamespaceResolver::default();
1051 let s = resolver.buffer.len();
1052 match resolver.push(&BytesStart::from_content(" xmlns:xmlns=''", 0)) {
1053 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
1054 assert_eq!(prefix, b"xmlns");
1055 assert_eq!(namespace, b"");
1056 }
1057 x => panic!(
1058 "Expected `Error::ReservedNamespaceError`, but found {:?}",
1059 x
1060 ),
1061 }
1062 assert_eq!(&resolver.buffer[s..], b"");
1063 }
1064
1065 /// Other prefix cannot be bound to `xmlns` namespace
1066 #[test]
1067 fn other_prefix_bound_to_xmlns_namespace() {
1068 let mut resolver = NamespaceResolver::default();
1069 let s = resolver.buffer.len();
1070 match resolver.push(&BytesStart::from_content(
1071 " xmlns:not_xmlns='http://www.w3.org/2000/xmlns/'",
1072 0,
1073 )) {
1074 Err(Error::InvalidPrefixBind { prefix, namespace }) => {
1075 assert_eq!(prefix, b"not_xmlns");
1076 assert_eq!(namespace, b"http://www.w3.org/2000/xmlns/");
1077 }
1078 x => panic!(
1079 "Expected `Error::ReservedNamespaceError`, but found {:?}",
1080 x
1081 ),
1082 }
1083 assert_eq!(&resolver.buffer[s..], b"");
1084 }
1085 }
1086 }
1087
1088 #[test]
1089 fn undeclared_prefix() {
1090 let name = QName(b"unknown:prefix");
1091
1092 let resolver = NamespaceResolver::default();
1093
1094 assert_eq!(
1095 resolver.buffer,
1096 b"xmlhttp://www.w3.org/XML/1998/namespacexmlnshttp://www.w3.org/2000/xmlns/"
1097 );
1098 assert_eq!(
1099 resolver.resolve(name, true),
1100 (Unknown(b"unknown".to_vec()), LocalName(b"prefix"))
1101 );
1102 assert_eq!(
1103 resolver.resolve(name, false),
1104 (Unknown(b"unknown".to_vec()), LocalName(b"prefix"))
1105 );
1106 assert_eq!(resolver.find(name), Unknown(b"unknown".to_vec()));
1107 }
1108
1109 /// Checks how the QName is decomposed to a prefix and a local name
1110 #[test]
1111 fn prefix_and_local_name() {
1112 let name = QName(b"foo:bus");
1113 assert_eq!(name.prefix(), Some(Prefix(b"foo")));
1114 assert_eq!(name.local_name(), LocalName(b"bus"));
1115 assert_eq!(name.decompose(), (LocalName(b"bus"), Some(Prefix(b"foo"))));
1116
1117 let name = QName(b"foo:");
1118 assert_eq!(name.prefix(), Some(Prefix(b"foo")));
1119 assert_eq!(name.local_name(), LocalName(b""));
1120 assert_eq!(name.decompose(), (LocalName(b""), Some(Prefix(b"foo"))));
1121
1122 let name = QName(b":foo");
1123 assert_eq!(name.prefix(), Some(Prefix(b"")));
1124 assert_eq!(name.local_name(), LocalName(b"foo"));
1125 assert_eq!(name.decompose(), (LocalName(b"foo"), Some(Prefix(b""))));
1126
1127 let name = QName(b"foo:bus:baz");
1128 assert_eq!(name.prefix(), Some(Prefix(b"foo")));
1129 assert_eq!(name.local_name(), LocalName(b"bus:baz"));
1130 assert_eq!(
1131 name.decompose(),
1132 (LocalName(b"bus:baz"), Some(Prefix(b"foo")))
1133 );
1134 }
1135}
1136