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::events::attributes::Attribute;
7use crate::events::BytesStart;
8use crate::utils::write_byte_string;
9use memchr::memchr;
10use std::fmt::{self, Debug, Formatter};
11
12/// Some namespace was invalid
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum NamespaceError {
15 /// Specified namespace prefix is unknown, cannot resolve namespace for it
16 UnknownPrefix(Vec<u8>),
17 /// Attempts to bind the `xml` prefix to something other than `http://www.w3.org/XML/1998/namespace`.
18 ///
19 /// `xml` prefix can be bound only to `http://www.w3.org/XML/1998/namespace`.
20 ///
21 /// Contains the namespace to which `xml` tried to be bound.
22 InvalidXmlPrefixBind(Vec<u8>),
23 /// Attempts to bind the `xmlns` prefix.
24 ///
25 /// `xmlns` prefix is always bound to `http://www.w3.org/2000/xmlns/` and cannot be bound
26 /// to any other namespace or even to `http://www.w3.org/2000/xmlns/`.
27 ///
28 /// Contains the namespace to which `xmlns` tried to be bound.
29 InvalidXmlnsPrefixBind(Vec<u8>),
30 /// Attempts to bind some prefix (except `xml`) to `http://www.w3.org/XML/1998/namespace`.
31 ///
32 /// Only `xml` prefix can be bound to `http://www.w3.org/XML/1998/namespace`.
33 ///
34 /// Contains the prefix that is tried to be bound.
35 InvalidPrefixForXml(Vec<u8>),
36 /// Attempts to bind some prefix to `http://www.w3.org/2000/xmlns/`.
37 ///
38 /// `http://www.w3.org/2000/xmlns/` cannot be bound to any prefix, even to `xmlns`.
39 ///
40 /// Contains the prefix that is tried to be bound.
41 InvalidPrefixForXmlns(Vec<u8>),
42}
43
44impl fmt::Display for NamespaceError {
45 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46 match self {
47 Self::UnknownPrefix(prefix) => {
48 f.write_str("unknown namespace prefix '")?;
49 write_byte_string(f, prefix)?;
50 f.write_str("'")
51 }
52 Self::InvalidXmlPrefixBind(namespace) => {
53 f.write_str("the namespace prefix 'xml' cannot be bound to '")?;
54 write_byte_string(f, namespace)?;
55 f.write_str("'")
56 }
57 Self::InvalidXmlnsPrefixBind(namespace) => {
58 f.write_str("the namespace prefix 'xmlns' cannot be bound to '")?;
59 write_byte_string(f, namespace)?;
60 f.write_str("'")
61 }
62 Self::InvalidPrefixForXml(prefix) => {
63 f.write_str("the namespace prefix '")?;
64 write_byte_string(f, prefix)?;
65 f.write_str("' cannot be bound to 'http://www.w3.org/XML/1998/namespace'")
66 }
67 Self::InvalidPrefixForXmlns(prefix) => {
68 f.write_str("the namespace prefix '")?;
69 write_byte_string(f, prefix)?;
70 f.write_str("' cannot be bound to 'http://www.w3.org/2000/xmlns/'")
71 }
72 }
73 }
74}
75
76impl std::error::Error for NamespaceError {}
77
78////////////////////////////////////////////////////////////////////////////////////////////////////
79
80/// A [qualified name] of an element or an attribute, including an optional
81/// namespace [prefix](Prefix) and a [local name](LocalName).
82///
83/// [qualified name]: https://www.w3.org/TR/xml-names11/#dt-qualname
84#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
85#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
86pub struct QName<'a>(pub &'a [u8]);
87impl<'a> QName<'a> {
88 /// Converts this name to an internal slice representation.
89 #[inline(always)]
90 pub const fn into_inner(self) -> &'a [u8] {
91 self.0
92 }
93
94 /// Returns local part of this qualified name.
95 ///
96 /// All content up to and including the first `:` character is removed from
97 /// the tag name.
98 ///
99 /// # Examples
100 ///
101 /// ```
102 /// # use quick_xml::name::QName;
103 /// let simple = QName(b"simple-name");
104 /// assert_eq!(simple.local_name().as_ref(), b"simple-name");
105 ///
106 /// let qname = QName(b"namespace:simple-name");
107 /// assert_eq!(qname.local_name().as_ref(), b"simple-name");
108 /// ```
109 pub fn local_name(&self) -> LocalName<'a> {
110 LocalName(self.index().map_or(self.0, |i| &self.0[i + 1..]))
111 }
112
113 /// Returns namespace part of this qualified name or `None` if namespace part
114 /// is not defined (symbol `':'` not found).
115 ///
116 /// # Examples
117 ///
118 /// ```
119 /// # use std::convert::AsRef;
120 /// # use quick_xml::name::QName;
121 /// let simple = QName(b"simple-name");
122 /// assert_eq!(simple.prefix(), None);
123 ///
124 /// let qname = QName(b"prefix:simple-name");
125 /// assert_eq!(qname.prefix().as_ref().map(|n| n.as_ref()), Some(b"prefix".as_ref()));
126 /// ```
127 pub fn prefix(&self) -> Option<Prefix<'a>> {
128 self.index().map(|i| Prefix(&self.0[..i]))
129 }
130
131 /// The same as `(qname.local_name(), qname.prefix())`, but does only one
132 /// lookup for a `':'` symbol.
133 pub fn decompose(&self) -> (LocalName<'a>, Option<Prefix<'a>>) {
134 match self.index() {
135 None => (LocalName(self.0), None),
136 Some(i) => (LocalName(&self.0[i + 1..]), Some(Prefix(&self.0[..i]))),
137 }
138 }
139
140 /// If that `QName` represents `"xmlns"` series of names, returns `Some`,
141 /// otherwise `None` is returned.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// # use quick_xml::name::{QName, PrefixDeclaration};
147 /// let qname = QName(b"xmlns");
148 /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Default));
149 ///
150 /// let qname = QName(b"xmlns:prefix");
151 /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"prefix")));
152 ///
153 /// // Be aware that this method does not check the validity of the prefix - it can be empty!
154 /// let qname = QName(b"xmlns:");
155 /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"")));
156 ///
157 /// let qname = QName(b"other-name");
158 /// assert_eq!(qname.as_namespace_binding(), None);
159 ///
160 /// // https://www.w3.org/TR/xml-names11/#xmlReserved
161 /// let qname = QName(b"xmlns-reserved-name");
162 /// assert_eq!(qname.as_namespace_binding(), None);
163 /// ```
164 pub fn as_namespace_binding(&self) -> Option<PrefixDeclaration<'a>> {
165 if self.0.starts_with(b"xmlns") {
166 return match self.0.get(5) {
167 None => Some(PrefixDeclaration::Default),
168 Some(&b':') => Some(PrefixDeclaration::Named(&self.0[6..])),
169 _ => None,
170 };
171 }
172 None
173 }
174
175 /// Returns the index in the name where prefix ended
176 #[inline(always)]
177 fn index(&self) -> Option<usize> {
178 memchr(b':', self.0)
179 }
180}
181impl<'a> Debug for QName<'a> {
182 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
183 write!(f, "QName(")?;
184 write_byte_string(f, self.0)?;
185 write!(f, ")")
186 }
187}
188impl<'a> AsRef<[u8]> for QName<'a> {
189 #[inline]
190 fn as_ref(&self) -> &[u8] {
191 self.0
192 }
193}
194
195////////////////////////////////////////////////////////////////////////////////////////////////////
196
197/// A [local (unqualified) name] of an element or an attribute, i.e. a name
198/// without [prefix](Prefix).
199///
200/// [local (unqualified) name]: https://www.w3.org/TR/xml-names11/#dt-localname
201#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
202#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
203pub struct LocalName<'a>(pub(crate) &'a [u8]);
204impl<'a> LocalName<'a> {
205 /// Converts this name to an internal slice representation.
206 #[inline(always)]
207 pub const fn into_inner(self) -> &'a [u8] {
208 self.0
209 }
210}
211impl<'a> Debug for LocalName<'a> {
212 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
213 write!(f, "LocalName(")?;
214 write_byte_string(f, self.0)?;
215 write!(f, ")")
216 }
217}
218impl<'a> AsRef<[u8]> for LocalName<'a> {
219 #[inline]
220 fn as_ref(&self) -> &[u8] {
221 self.0
222 }
223}
224impl<'a> From<QName<'a>> for LocalName<'a> {
225 /// Creates `LocalName` from a [`QName`]
226 ///
227 /// # Examples
228 ///
229 /// ```
230 /// # use quick_xml::name::{LocalName, QName};
231 ///
232 /// let local: LocalName = QName(b"unprefixed").into();
233 /// assert_eq!(local.as_ref(), b"unprefixed");
234 ///
235 /// let local: LocalName = QName(b"some:prefix").into();
236 /// assert_eq!(local.as_ref(), b"prefix");
237 /// ```
238 #[inline]
239 fn from(name: QName<'a>) -> Self {
240 Self(name.index().map_or(name.0, |i| &name.0[i + 1..]))
241 }
242}
243
244////////////////////////////////////////////////////////////////////////////////////////////////////
245
246/// A [namespace prefix] part of the [qualified name](QName) of an element tag
247/// or an attribute: a `prefix` in `<prefix:local-element-name>` or
248/// `prefix:local-attribute-name="attribute value"`.
249///
250/// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix
251#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
252#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
253pub struct Prefix<'a>(&'a [u8]);
254impl<'a> Prefix<'a> {
255 /// Extracts internal slice
256 #[inline(always)]
257 pub const fn into_inner(self) -> &'a [u8] {
258 self.0
259 }
260
261 /// Checks if this prefix is a special prefix `xml`.
262 #[inline(always)]
263 pub const fn is_xml(&self) -> bool {
264 matches!(self.0, b"xml")
265 }
266
267 /// Checks if this prefix is a special prefix `xmlns`.
268 #[inline(always)]
269 pub const fn is_xmlns(&self) -> bool {
270 matches!(self.0, b"xmlns")
271 }
272}
273impl<'a> Debug for Prefix<'a> {
274 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
275 write!(f, "Prefix(")?;
276 write_byte_string(f, self.0)?;
277 write!(f, ")")
278 }
279}
280impl<'a> AsRef<[u8]> for Prefix<'a> {
281 #[inline]
282 fn as_ref(&self) -> &[u8] {
283 self.0
284 }
285}
286
287////////////////////////////////////////////////////////////////////////////////////////////////////
288
289/// A namespace prefix declaration, `xmlns` or `xmlns:<name>`, as defined in
290/// [XML Schema specification](https://www.w3.org/TR/xml-names11/#ns-decl)
291#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
292pub enum PrefixDeclaration<'a> {
293 /// XML attribute binds a default namespace. Corresponds to `xmlns` in `xmlns="..."`
294 Default,
295 /// XML attribute binds a specified prefix to a namespace. Corresponds to a
296 /// `prefix` in `xmlns:prefix="..."`, which is stored as payload of this variant.
297 Named(&'a [u8]),
298}
299
300////////////////////////////////////////////////////////////////////////////////////////////////////
301
302/// A [namespace name] that is declared in a `xmlns[:prefix]="namespace name"`.
303///
304/// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
305#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
306#[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))]
307pub struct Namespace<'a>(pub &'a [u8]);
308impl<'a> Namespace<'a> {
309 /// Converts this namespace to an internal slice representation.
310 ///
311 /// This is [non-normalized] attribute value, i.e. any entity references is
312 /// not expanded and space characters are not removed. This means, that
313 /// different byte slices, returned from this method, can represent the same
314 /// namespace and would be treated by parser as identical.
315 ///
316 /// For example, if the entity **eacute** has been defined to be **é**,
317 /// the empty tags below all contain namespace declarations binding the
318 /// prefix `p` to the same [IRI reference], `http://example.org/rosé`.
319 ///
320 /// ```xml
321 /// <p:foo xmlns:p="http://example.org/rosé" />
322 /// <p:foo xmlns:p="http://example.org/rosé" />
323 /// <p:foo xmlns:p="http://example.org/rosé" />
324 /// <p:foo xmlns:p="http://example.org/rosé" />
325 /// <p:foo xmlns:p="http://example.org/rosé" />
326 /// ```
327 ///
328 /// This is because XML entity references are expanded during attribute value
329 /// normalization.
330 ///
331 /// [non-normalized]: https://www.w3.org/TR/xml11/#AVNormalize
332 /// [IRI reference]: https://datatracker.ietf.org/doc/html/rfc3987
333 #[inline(always)]
334 pub const fn into_inner(self) -> &'a [u8] {
335 self.0
336 }
337 //TODO: implement value normalization and use it when comparing namespaces
338}
339impl<'a> Debug for Namespace<'a> {
340 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
341 write!(f, "Namespace(")?;
342 write_byte_string(f, self.0)?;
343 write!(f, ")")
344 }
345}
346impl<'a> AsRef<[u8]> for Namespace<'a> {
347 #[inline]
348 fn as_ref(&self) -> &[u8] {
349 self.0
350 }
351}
352
353////////////////////////////////////////////////////////////////////////////////////////////////////
354
355/// Result of [prefix] resolution which creates by [`NsReader::resolve_attribute`],
356/// [`NsReader::resolve_element`], [`NsReader::read_resolved_event`] and
357/// [`NsReader::read_resolved_event_into`] methods.
358///
359/// [prefix]: Prefix
360/// [`NsReader::resolve_attribute`]: crate::reader::NsReader::resolve_attribute
361/// [`NsReader::resolve_element`]: crate::reader::NsReader::resolve_element
362/// [`NsReader::read_resolved_event`]: crate::reader::NsReader::read_resolved_event
363/// [`NsReader::read_resolved_event_into`]: crate::reader::NsReader::read_resolved_event_into
364#[derive(Clone, PartialEq, Eq, Hash)]
365pub enum ResolveResult<'ns> {
366 /// Qualified name does not contain prefix, and resolver does not define
367 /// default namespace, so name is not bound to any namespace
368 Unbound,
369 /// [`Prefix`] resolved to the specified namespace
370 Bound(Namespace<'ns>),
371 /// Specified prefix was not found in scope
372 Unknown(Vec<u8>),
373}
374impl<'ns> Debug for ResolveResult<'ns> {
375 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
376 match self {
377 Self::Unbound => write!(f, "Unbound"),
378 Self::Bound(ns) => write!(f, "Bound({:?})", ns),
379 Self::Unknown(p) => {
380 write!(f, "Unknown(")?;
381 write_byte_string(f, p)?;
382 write!(f, ")")
383 }
384 }
385 }
386}
387
388impl<'ns> TryFrom<ResolveResult<'ns>> for Option<Namespace<'ns>> {
389 type Error = NamespaceError;
390
391 /// Try to convert this result to an optional namespace and returns
392 /// [`NamespaceError::UnknownPrefix`] if this result represents unknown prefix
393 fn try_from(result: ResolveResult<'ns>) -> Result<Self, NamespaceError> {
394 use ResolveResult::*;
395
396 match result {
397 Unbound => Ok(None),
398 Bound(ns) => Ok(Some(ns)),
399 Unknown(p) => Err(NamespaceError::UnknownPrefix(p)),
400 }
401 }
402}
403
404////////////////////////////////////////////////////////////////////////////////////////////////////
405
406/// An entry that contains index into the buffer with namespace bindings.
407///
408/// Defines a mapping from *[namespace prefix]* to *[namespace name]*.
409/// If prefix is empty, defines a *default namespace* binding that applies to
410/// unprefixed element names (unprefixed attribute names do not bind to any
411/// namespace and they processing is dependent on the element in which their
412/// defined).
413///
414/// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix
415/// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
416#[derive(Debug, Clone)]
417struct NamespaceEntry {
418 /// Index of the namespace in the buffer
419 start: usize,
420 /// Length of the prefix
421 /// * if greater than zero, then binds this namespace to the slice
422 /// `[start..start + prefix_len]` in the buffer.
423 /// * else defines the current default namespace.
424 prefix_len: usize,
425 /// The length of a namespace name (the URI) of this namespace declaration.
426 /// Name started just after prefix and extend for `value_len` bytes.
427 ///
428 /// The XML standard [specifies] that an empty namespace value 'removes' a namespace declaration
429 /// for the extent of its scope. For prefix declarations that's not very interesting, but it is
430 /// vital for default namespace declarations. With `xmlns=""` you can revert back to the default
431 /// behaviour of leaving unqualified element names unqualified.
432 ///
433 /// [specifies]: https://www.w3.org/TR/xml-names11/#scoping
434 value_len: usize,
435 /// Level of nesting at which this namespace was declared. The declaring element is included,
436 /// i.e., a declaration on the document root has `level = 1`.
437 /// This is used to pop the namespace when the element gets closed.
438 level: i32,
439}
440
441impl NamespaceEntry {
442 /// Get the namespace prefix, bound to this namespace declaration, or `None`,
443 /// if this declaration is for default namespace (`xmlns="..."`).
444 #[inline]
445 fn prefix<'b>(&self, ns_buffer: &'b [u8]) -> Option<Prefix<'b>> {
446 if self.prefix_len == 0 {
447 None
448 } else {
449 Some(Prefix(&ns_buffer[self.start..self.start + self.prefix_len]))
450 }
451 }
452
453 /// Gets the namespace name (the URI) slice out of namespace buffer
454 ///
455 /// Returns `None` if namespace for this prefix was explicitly removed from
456 /// scope, using `xmlns[:prefix]=""`
457 #[inline]
458 fn namespace<'ns>(&self, buffer: &'ns [u8]) -> ResolveResult<'ns> {
459 if self.value_len == 0 {
460 ResolveResult::Unbound
461 } else {
462 let start = self.start + self.prefix_len;
463 ResolveResult::Bound(Namespace(&buffer[start..start + self.value_len]))
464 }
465 }
466}
467
468/// A namespace management buffer.
469///
470/// Holds all internal logic to push/pop namespaces with their levels.
471#[derive(Debug, Clone)]
472pub(crate) struct NamespaceResolver {
473 /// Buffer that contains names of namespace prefixes (the part between `xmlns:`
474 /// and an `=`) and namespace values.
475 buffer: Vec<u8>,
476 /// A stack of namespace bindings to prefixes that currently in scope
477 bindings: Vec<NamespaceEntry>,
478 /// The number of open tags at the moment. We need to keep track of this to know which namespace
479 /// declarations to remove when we encounter an `End` event.
480 nesting_level: i32,
481}
482
483/// That constant define the one of [reserved namespaces] for the xml standard.
484///
485/// The prefix `xml` is by definition bound to the namespace name
486/// `http://www.w3.org/XML/1998/namespace`. It may, but need not, be declared, and must not be
487/// undeclared or bound to any other namespace name. Other prefixes must not be bound to this
488/// namespace name, and it must not be declared as the default namespace.
489///
490/// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
491const RESERVED_NAMESPACE_XML: (Prefix, Namespace) = (
492 Prefix(b"xml"),
493 Namespace(b"http://www.w3.org/XML/1998/namespace"),
494);
495/// That constant define the one of [reserved namespaces] for the xml standard.
496///
497/// The prefix `xmlns` is used only to declare namespace bindings and is by definition bound
498/// to the namespace name `http://www.w3.org/2000/xmlns/`. It must not be declared or
499/// undeclared. Other prefixes must not be bound to this namespace name, and it must not be
500/// declared as the default namespace. Element names must not have the prefix `xmlns`.
501///
502/// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
503const RESERVED_NAMESPACE_XMLNS: (Prefix, Namespace) = (
504 Prefix(b"xmlns"),
505 Namespace(b"http://www.w3.org/2000/xmlns/"),
506);
507
508impl Default for NamespaceResolver {
509 fn default() -> Self {
510 let mut buffer = Vec::new();
511 let mut bindings = Vec::new();
512 for ent in &[RESERVED_NAMESPACE_XML, RESERVED_NAMESPACE_XMLNS] {
513 let prefix = ent.0.into_inner();
514 let uri = ent.1.into_inner();
515 bindings.push(NamespaceEntry {
516 start: buffer.len(),
517 prefix_len: prefix.len(),
518 value_len: uri.len(),
519 level: 0,
520 });
521 buffer.extend(prefix);
522 buffer.extend(uri);
523 }
524
525 Self {
526 buffer,
527 bindings,
528 nesting_level: 0,
529 }
530 }
531}
532
533impl NamespaceResolver {
534 /// Begins a new scope and add to it all [namespace bindings] that found in
535 /// the specified start element.
536 ///
537 /// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
538 pub fn push(&mut self, start: &BytesStart) -> Result<(), NamespaceError> {
539 self.nesting_level += 1;
540 let level = self.nesting_level;
541 // adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns'
542 // (default namespace) attribute.
543 for a in start.attributes().with_checks(false) {
544 if let Ok(Attribute { key: k, value: v }) = a {
545 match k.as_namespace_binding() {
546 Some(PrefixDeclaration::Default) => {
547 let start = self.buffer.len();
548 self.buffer.extend_from_slice(&v);
549 self.bindings.push(NamespaceEntry {
550 start,
551 prefix_len: 0,
552 value_len: v.len(),
553 level,
554 });
555 }
556 Some(PrefixDeclaration::Named(b"xml")) => {
557 if Namespace(&v) != RESERVED_NAMESPACE_XML.1 {
558 // error, `xml` prefix explicitly set to different value
559 return Err(NamespaceError::InvalidXmlPrefixBind(v.to_vec()));
560 }
561 // don't add another NamespaceEntry for the `xml` namespace prefix
562 }
563 Some(PrefixDeclaration::Named(b"xmlns")) => {
564 // error, `xmlns` prefix explicitly set
565 return Err(NamespaceError::InvalidXmlnsPrefixBind(v.to_vec()));
566 }
567 Some(PrefixDeclaration::Named(prefix)) => {
568 let ns = Namespace(&v);
569
570 if ns == RESERVED_NAMESPACE_XML.1 {
571 // error, non-`xml` prefix set to xml uri
572 return Err(NamespaceError::InvalidPrefixForXml(prefix.to_vec()));
573 } else if ns == RESERVED_NAMESPACE_XMLNS.1 {
574 // error, non-`xmlns` prefix set to xmlns uri
575 return Err(NamespaceError::InvalidPrefixForXmlns(prefix.to_vec()));
576 }
577
578 let start = self.buffer.len();
579 self.buffer.extend_from_slice(prefix);
580 self.buffer.extend_from_slice(&v);
581 self.bindings.push(NamespaceEntry {
582 start,
583 prefix_len: prefix.len(),
584 value_len: v.len(),
585 level,
586 });
587 }
588 None => {}
589 }
590 } else {
591 break;
592 }
593 }
594 Ok(())
595 }
596
597 /// Ends a top-most scope by popping all [namespace binding], that was added by
598 /// last call to [`Self::push()`].
599 ///
600 /// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
601 pub fn pop(&mut self) {
602 self.nesting_level -= 1;
603 let current_level = self.nesting_level;
604 // from the back (most deeply nested scope), look for the first scope that is still valid
605 match self.bindings.iter().rposition(|n| n.level <= current_level) {
606 // none of the namespaces are valid, remove all of them
607 None => {
608 self.buffer.clear();
609 self.bindings.clear();
610 }
611 // drop all namespaces past the last valid namespace
612 Some(last_valid_pos) => {
613 if let Some(len) = self.bindings.get(last_valid_pos + 1).map(|n| n.start) {
614 self.buffer.truncate(len);
615 self.bindings.truncate(last_valid_pos + 1);
616 }
617 }
618 }
619 }
620
621 /// Resolves a potentially qualified **element name** or **attribute name**
622 /// into (namespace name, local name).
623 ///
624 /// *Qualified* names have the form `prefix:local-name` where the `prefix` is
625 /// defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`.
626 /// The namespace prefix can be defined on the same element as the element or
627 /// attribute in question.
628 ///
629 /// *Unqualified* attribute names do *not* inherit the current *default namespace*.
630 ///
631 /// # Lifetimes
632 ///
633 /// - `'n`: lifetime of an attribute or an element name
634 #[inline]
635 pub fn resolve<'n>(
636 &self,
637 name: QName<'n>,
638 use_default: bool,
639 ) -> (ResolveResult, LocalName<'n>) {
640 let (local_name, prefix) = name.decompose();
641 (self.resolve_prefix(prefix, use_default), local_name)
642 }
643
644 /// Finds a [namespace name] for a given qualified **element name**, borrow
645 /// it from the internal buffer.
646 ///
647 /// Returns `None`, if:
648 /// - name is unqualified
649 /// - prefix not found in the current scope
650 /// - prefix was [unbound] using `xmlns:prefix=""`
651 ///
652 /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName
653 /// [unbound]: https://www.w3.org/TR/xml-names11/#scoping
654 #[inline]
655 pub fn find(&self, element_name: QName) -> ResolveResult {
656 self.resolve_prefix(element_name.prefix(), true)
657 }
658
659 fn resolve_prefix(&self, prefix: Option<Prefix>, use_default: bool) -> ResolveResult {
660 self.bindings
661 .iter()
662 // Find the last defined binding that corresponds to the given prefix
663 .rev()
664 .find_map(|n| match (n.prefix(&self.buffer), prefix) {
665 // This is default namespace definition and name has no explicit prefix
666 (None, None) if use_default => Some(n.namespace(&self.buffer)),
667 (None, None) => Some(ResolveResult::Unbound),
668
669 // One part has prefix but other is not -> skip
670 (None, Some(_)) => None,
671 (Some(_), None) => None,
672
673 // Prefixes does not match -> skip
674 (Some(definition), Some(usage)) if definition != usage => None,
675
676 // Prefixes the same, entry defines binding reset (corresponds to `xmlns:p=""`)
677 _ if n.value_len == 0 => Some(Self::maybe_unknown(prefix)),
678 // Prefixes the same, returns corresponding namespace
679 _ => Some(n.namespace(&self.buffer)),
680 })
681 .unwrap_or_else(|| Self::maybe_unknown(prefix))
682 }
683
684 #[inline]
685 fn maybe_unknown(prefix: Option<Prefix>) -> ResolveResult<'static> {
686 match prefix {
687 Some(p) => ResolveResult::Unknown(p.into_inner().to_vec()),
688 None => ResolveResult::Unbound,
689 }
690 }
691
692 #[inline]
693 pub const fn iter(&self) -> PrefixIter {
694 PrefixIter {
695 resolver: self,
696 // We initialize the cursor to 2 to skip the two default namespaces xml: and xmlns:
697 bindings_cursor: 2,
698 }
699 }
700}
701
702////////////////////////////////////////////////////////////////////////////////////////////////////
703
704/// Iterator on the current declared prefixes.
705///
706/// See [`NsReader::prefixes`](crate::NsReader::prefixes) for documentation.
707#[derive(Debug, Clone)]
708pub struct PrefixIter<'a> {
709 resolver: &'a NamespaceResolver,
710 bindings_cursor: usize,
711}
712
713impl<'a> Iterator for PrefixIter<'a> {
714 type Item = (PrefixDeclaration<'a>, Namespace<'a>);
715
716 fn next(&mut self) -> Option<(PrefixDeclaration<'a>, Namespace<'a>)> {
717 while let Some(namespace_entry) = self.resolver.bindings.get(self.bindings_cursor) {
718 self.bindings_cursor += 1; // We increment for next read
719
720 // We check if the key has not been overridden by having a look
721 // at the namespaces declared after in the array
722 let prefix = namespace_entry.prefix(&self.resolver.buffer);
723 if self.resolver.bindings[self.bindings_cursor..]
724 .iter()
725 .any(|ne| prefix == ne.prefix(&self.resolver.buffer))
726 {
727 continue; // Overridden
728 }
729 let namespace = if let ResolveResult::Bound(namespace) =
730 namespace_entry.namespace(&self.resolver.buffer)
731 {
732 namespace
733 } else {
734 continue; // We don't return unbound namespaces
735 };
736 let prefix = if let Some(Prefix(prefix)) = prefix {
737 PrefixDeclaration::Named(prefix)
738 } else {
739 PrefixDeclaration::Default
740 };
741 return Some((prefix, namespace));
742 }
743 None // We have exhausted the array
744 }
745
746 fn size_hint(&self) -> (usize, Option<usize>) {
747 // Real count could be less if some namespaces was overridden
748 (0, Some(self.resolver.bindings.len() - self.bindings_cursor))
749 }
750}
751
752#[cfg(test)]
753mod namespaces {
754 use super::*;
755 use pretty_assertions::assert_eq;
756 use ResolveResult::*;
757
758 /// Unprefixed attribute names (resolved with `false` flag) never have a namespace
759 /// according to <https://www.w3.org/TR/xml-names11/#defaulting>:
760 ///
761 /// > A default namespace declaration applies to all unprefixed element names
762 /// > within its scope. Default namespace declarations do not apply directly
763 /// > to attribute names; the interpretation of unprefixed attributes is
764 /// > determined by the element on which they appear.
765 mod unprefixed {
766 use super::*;
767 use pretty_assertions::assert_eq;
768
769 /// Basic tests that checks that basic resolver functionality is working
770 #[test]
771 fn basic() {
772 let name = QName(b"simple");
773 let ns = Namespace(b"default");
774
775 let mut resolver = NamespaceResolver::default();
776 let s = resolver.buffer.len();
777
778 resolver
779 .push(&BytesStart::from_content(" xmlns='default'", 0))
780 .unwrap();
781 assert_eq!(&resolver.buffer[s..], b"default");
782
783 // Check that tags without namespaces does not change result
784 resolver.push(&BytesStart::from_content("", 0)).unwrap();
785 assert_eq!(&resolver.buffer[s..], b"default");
786 resolver.pop();
787
788 assert_eq!(&resolver.buffer[s..], b"default");
789 assert_eq!(
790 resolver.resolve(name, true),
791 (Bound(ns), LocalName(b"simple"))
792 );
793 assert_eq!(
794 resolver.resolve(name, false),
795 (Unbound, LocalName(b"simple"))
796 );
797 assert_eq!(resolver.find(name), Bound(ns));
798 }
799
800 /// Test adding a second level of namespaces, which replaces the previous binding
801 #[test]
802 fn override_namespace() {
803 let name = QName(b"simple");
804 let old_ns = Namespace(b"old");
805 let new_ns = Namespace(b"new");
806
807 let mut resolver = NamespaceResolver::default();
808 let s = resolver.buffer.len();
809
810 resolver
811 .push(&BytesStart::from_content(" xmlns='old'", 0))
812 .unwrap();
813 resolver
814 .push(&BytesStart::from_content(" xmlns='new'", 0))
815 .unwrap();
816
817 assert_eq!(&resolver.buffer[s..], b"oldnew");
818 assert_eq!(
819 resolver.resolve(name, true),
820 (Bound(new_ns), LocalName(b"simple"))
821 );
822 assert_eq!(
823 resolver.resolve(name, false),
824 (Unbound, LocalName(b"simple"))
825 );
826 assert_eq!(resolver.find(name), Bound(new_ns));
827
828 resolver.pop();
829 assert_eq!(&resolver.buffer[s..], b"old");
830 assert_eq!(
831 resolver.resolve(name, true),
832 (Bound(old_ns), LocalName(b"simple"))
833 );
834 assert_eq!(
835 resolver.resolve(name, false),
836 (Unbound, LocalName(b"simple"))
837 );
838 assert_eq!(resolver.find(name), Bound(old_ns));
839 }
840
841 /// Test adding a second level of namespaces, which reset the previous binding
842 /// to not bound state by specifying an empty namespace name.
843 ///
844 /// See <https://www.w3.org/TR/xml-names11/#scoping>
845 #[test]
846 fn reset() {
847 let name = QName(b"simple");
848 let old_ns = Namespace(b"old");
849
850 let mut resolver = NamespaceResolver::default();
851 let s = resolver.buffer.len();
852
853 resolver
854 .push(&BytesStart::from_content(" xmlns='old'", 0))
855 .unwrap();
856 resolver
857 .push(&BytesStart::from_content(" xmlns=''", 0))
858 .unwrap();
859
860 assert_eq!(&resolver.buffer[s..], b"old");
861 assert_eq!(
862 resolver.resolve(name, true),
863 (Unbound, LocalName(b"simple"))
864 );
865 assert_eq!(
866 resolver.resolve(name, false),
867 (Unbound, LocalName(b"simple"))
868 );
869 assert_eq!(resolver.find(name), Unbound);
870
871 resolver.pop();
872 assert_eq!(&resolver.buffer[s..], b"old");
873 assert_eq!(
874 resolver.resolve(name, true),
875 (Bound(old_ns), LocalName(b"simple"))
876 );
877 assert_eq!(
878 resolver.resolve(name, false),
879 (Unbound, LocalName(b"simple"))
880 );
881 assert_eq!(resolver.find(name), Bound(old_ns));
882 }
883 }
884
885 mod declared_prefix {
886 use super::*;
887 use pretty_assertions::assert_eq;
888
889 /// Basic tests that checks that basic resolver functionality is working
890 #[test]
891 fn basic() {
892 let name = QName(b"p:with-declared-prefix");
893 let ns = Namespace(b"default");
894
895 let mut resolver = NamespaceResolver::default();
896 let s = resolver.buffer.len();
897
898 resolver
899 .push(&BytesStart::from_content(" xmlns:p='default'", 0))
900 .unwrap();
901 assert_eq!(&resolver.buffer[s..], b"pdefault");
902
903 // Check that tags without namespaces does not change result
904 resolver.push(&BytesStart::from_content("", 0)).unwrap();
905 assert_eq!(&resolver.buffer[s..], b"pdefault");
906 resolver.pop();
907
908 assert_eq!(&resolver.buffer[s..], b"pdefault");
909 assert_eq!(
910 resolver.resolve(name, true),
911 (Bound(ns), LocalName(b"with-declared-prefix"))
912 );
913 assert_eq!(
914 resolver.resolve(name, false),
915 (Bound(ns), LocalName(b"with-declared-prefix"))
916 );
917 assert_eq!(resolver.find(name), Bound(ns));
918 }
919
920 /// Test adding a second level of namespaces, which replaces the previous binding
921 #[test]
922 fn override_namespace() {
923 let name = QName(b"p:with-declared-prefix");
924 let old_ns = Namespace(b"old");
925 let new_ns = Namespace(b"new");
926
927 let mut resolver = NamespaceResolver::default();
928 let s = resolver.buffer.len();
929
930 resolver
931 .push(&BytesStart::from_content(" xmlns:p='old'", 0))
932 .unwrap();
933 resolver
934 .push(&BytesStart::from_content(" xmlns:p='new'", 0))
935 .unwrap();
936
937 assert_eq!(&resolver.buffer[s..], b"poldpnew");
938 assert_eq!(
939 resolver.resolve(name, true),
940 (Bound(new_ns), LocalName(b"with-declared-prefix"))
941 );
942 assert_eq!(
943 resolver.resolve(name, false),
944 (Bound(new_ns), LocalName(b"with-declared-prefix"))
945 );
946 assert_eq!(resolver.find(name), Bound(new_ns));
947
948 resolver.pop();
949 assert_eq!(&resolver.buffer[s..], b"pold");
950 assert_eq!(
951 resolver.resolve(name, true),
952 (Bound(old_ns), LocalName(b"with-declared-prefix"))
953 );
954 assert_eq!(
955 resolver.resolve(name, false),
956 (Bound(old_ns), LocalName(b"with-declared-prefix"))
957 );
958 assert_eq!(resolver.find(name), Bound(old_ns));
959 }
960
961 /// Test adding a second level of namespaces, which reset the previous binding
962 /// to not bound state by specifying an empty namespace name.
963 ///
964 /// See <https://www.w3.org/TR/xml-names11/#scoping>
965 #[test]
966 fn reset() {
967 let name = QName(b"p:with-declared-prefix");
968 let old_ns = Namespace(b"old");
969
970 let mut resolver = NamespaceResolver::default();
971 let s = resolver.buffer.len();
972
973 resolver
974 .push(&BytesStart::from_content(" xmlns:p='old'", 0))
975 .unwrap();
976 resolver
977 .push(&BytesStart::from_content(" xmlns:p=''", 0))
978 .unwrap();
979
980 assert_eq!(&resolver.buffer[s..], b"poldp");
981 assert_eq!(
982 resolver.resolve(name, true),
983 (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix"))
984 );
985 assert_eq!(
986 resolver.resolve(name, false),
987 (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix"))
988 );
989 assert_eq!(resolver.find(name), Unknown(b"p".to_vec()));
990
991 resolver.pop();
992 assert_eq!(&resolver.buffer[s..], b"pold");
993 assert_eq!(
994 resolver.resolve(name, true),
995 (Bound(old_ns), LocalName(b"with-declared-prefix"))
996 );
997 assert_eq!(
998 resolver.resolve(name, false),
999 (Bound(old_ns), LocalName(b"with-declared-prefix"))
1000 );
1001 assert_eq!(resolver.find(name), Bound(old_ns));
1002 }
1003 }
1004
1005 /// Tests for `xml` and `xmlns` built-in prefixes.
1006 ///
1007 /// See <https://www.w3.org/TR/xml-names11/#xmlReserved>
1008 mod builtin_prefixes {
1009 use super::*;
1010
1011 mod xml {
1012 use super::*;
1013 use pretty_assertions::assert_eq;
1014
1015 /// `xml` prefix are always defined, it is not required to define it explicitly.
1016 #[test]
1017 fn undeclared() {
1018 let name = QName(b"xml:random");
1019 let namespace = RESERVED_NAMESPACE_XML.1;
1020
1021 let resolver = NamespaceResolver::default();
1022
1023 assert_eq!(
1024 resolver.resolve(name, true),
1025 (Bound(namespace), LocalName(b"random"))
1026 );
1027
1028 assert_eq!(
1029 resolver.resolve(name, false),
1030 (Bound(namespace), LocalName(b"random"))
1031 );
1032 assert_eq!(resolver.find(name), Bound(namespace));
1033 }
1034
1035 /// `xml` prefix can be declared but it must be bound to the value
1036 /// `http://www.w3.org/XML/1998/namespace`
1037 #[test]
1038 fn rebound_to_correct_ns() {
1039 let mut resolver = NamespaceResolver::default();
1040 let s = resolver.buffer.len();
1041 resolver.push(
1042 &BytesStart::from_content(
1043 " xmlns:xml='http://www.w3.org/XML/1998/namespace'",
1044 0,
1045 ),
1046 ).expect("`xml` prefix should be possible to bound to `http://www.w3.org/XML/1998/namespace`");
1047 assert_eq!(&resolver.buffer[s..], b"");
1048 }
1049
1050 /// `xml` prefix cannot be re-declared to another namespace
1051 #[test]
1052 fn rebound_to_incorrect_ns() {
1053 let mut resolver = NamespaceResolver::default();
1054 let s = resolver.buffer.len();
1055 assert_eq!(
1056 resolver.push(&BytesStart::from_content(
1057 " xmlns:xml='not_correct_namespace'",
1058 0,
1059 )),
1060 Err(NamespaceError::InvalidXmlPrefixBind(
1061 b"not_correct_namespace".to_vec()
1062 )),
1063 );
1064 assert_eq!(&resolver.buffer[s..], b"");
1065 }
1066
1067 /// `xml` prefix cannot be unbound
1068 #[test]
1069 fn unbound() {
1070 let mut resolver = NamespaceResolver::default();
1071 let s = resolver.buffer.len();
1072 assert_eq!(
1073 resolver.push(&BytesStart::from_content(" xmlns:xml=''", 0)),
1074 Err(NamespaceError::InvalidXmlPrefixBind(b"".to_vec())),
1075 );
1076 assert_eq!(&resolver.buffer[s..], b"");
1077 }
1078
1079 /// Other prefix cannot be bound to `xml` namespace
1080 #[test]
1081 fn other_prefix_bound_to_xml_namespace() {
1082 let mut resolver = NamespaceResolver::default();
1083 let s = resolver.buffer.len();
1084 assert_eq!(
1085 resolver.push(&BytesStart::from_content(
1086 " xmlns:not_xml='http://www.w3.org/XML/1998/namespace'",
1087 0,
1088 )),
1089 Err(NamespaceError::InvalidPrefixForXml(b"not_xml".to_vec())),
1090 );
1091 assert_eq!(&resolver.buffer[s..], b"");
1092 }
1093 }
1094
1095 mod xmlns {
1096 use super::*;
1097 use pretty_assertions::assert_eq;
1098
1099 /// `xmlns` prefix are always defined, it is forbidden to define it explicitly
1100 #[test]
1101 fn undeclared() {
1102 let name = QName(b"xmlns:random");
1103 let namespace = RESERVED_NAMESPACE_XMLNS.1;
1104
1105 let resolver = NamespaceResolver::default();
1106
1107 assert_eq!(
1108 resolver.resolve(name, true),
1109 (Bound(namespace), LocalName(b"random"))
1110 );
1111
1112 assert_eq!(
1113 resolver.resolve(name, false),
1114 (Bound(namespace), LocalName(b"random"))
1115 );
1116 assert_eq!(resolver.find(name), Bound(namespace));
1117 }
1118
1119 /// `xmlns` prefix cannot be re-declared event to its own namespace
1120 #[test]
1121 fn rebound_to_correct_ns() {
1122 let mut resolver = NamespaceResolver::default();
1123 let s = resolver.buffer.len();
1124 assert_eq!(
1125 resolver.push(&BytesStart::from_content(
1126 " xmlns:xmlns='http://www.w3.org/2000/xmlns/'",
1127 0,
1128 )),
1129 Err(NamespaceError::InvalidXmlnsPrefixBind(
1130 b"http://www.w3.org/2000/xmlns/".to_vec()
1131 )),
1132 );
1133 assert_eq!(&resolver.buffer[s..], b"");
1134 }
1135
1136 /// `xmlns` prefix cannot be re-declared
1137 #[test]
1138 fn rebound_to_incorrect_ns() {
1139 let mut resolver = NamespaceResolver::default();
1140 let s = resolver.buffer.len();
1141 assert_eq!(
1142 resolver.push(&BytesStart::from_content(
1143 " xmlns:xmlns='not_correct_namespace'",
1144 0,
1145 )),
1146 Err(NamespaceError::InvalidXmlnsPrefixBind(
1147 b"not_correct_namespace".to_vec()
1148 )),
1149 );
1150 assert_eq!(&resolver.buffer[s..], b"");
1151 }
1152
1153 /// `xmlns` prefix cannot be unbound
1154 #[test]
1155 fn unbound() {
1156 let mut resolver = NamespaceResolver::default();
1157 let s = resolver.buffer.len();
1158 assert_eq!(
1159 resolver.push(&BytesStart::from_content(" xmlns:xmlns=''", 0)),
1160 Err(NamespaceError::InvalidXmlnsPrefixBind(b"".to_vec())),
1161 );
1162 assert_eq!(&resolver.buffer[s..], b"");
1163 }
1164
1165 /// Other prefix cannot be bound to `xmlns` namespace
1166 #[test]
1167 fn other_prefix_bound_to_xmlns_namespace() {
1168 let mut resolver = NamespaceResolver::default();
1169 let s = resolver.buffer.len();
1170 assert_eq!(
1171 resolver.push(&BytesStart::from_content(
1172 " xmlns:not_xmlns='http://www.w3.org/2000/xmlns/'",
1173 0,
1174 )),
1175 Err(NamespaceError::InvalidPrefixForXmlns(b"not_xmlns".to_vec())),
1176 );
1177 assert_eq!(&resolver.buffer[s..], b"");
1178 }
1179 }
1180 }
1181
1182 #[test]
1183 fn undeclared_prefix() {
1184 let name = QName(b"unknown:prefix");
1185
1186 let resolver = NamespaceResolver::default();
1187
1188 assert_eq!(
1189 resolver.buffer,
1190 b"xmlhttp://www.w3.org/XML/1998/namespacexmlnshttp://www.w3.org/2000/xmlns/"
1191 );
1192 assert_eq!(
1193 resolver.resolve(name, true),
1194 (Unknown(b"unknown".to_vec()), LocalName(b"prefix"))
1195 );
1196 assert_eq!(
1197 resolver.resolve(name, false),
1198 (Unknown(b"unknown".to_vec()), LocalName(b"prefix"))
1199 );
1200 assert_eq!(resolver.find(name), Unknown(b"unknown".to_vec()));
1201 }
1202
1203 /// Checks how the QName is decomposed to a prefix and a local name
1204 #[test]
1205 fn prefix_and_local_name() {
1206 let name = QName(b"foo:bus");
1207 assert_eq!(name.prefix(), Some(Prefix(b"foo")));
1208 assert_eq!(name.local_name(), LocalName(b"bus"));
1209 assert_eq!(name.decompose(), (LocalName(b"bus"), Some(Prefix(b"foo"))));
1210
1211 let name = QName(b"foo:");
1212 assert_eq!(name.prefix(), Some(Prefix(b"foo")));
1213 assert_eq!(name.local_name(), LocalName(b""));
1214 assert_eq!(name.decompose(), (LocalName(b""), Some(Prefix(b"foo"))));
1215
1216 let name = QName(b":foo");
1217 assert_eq!(name.prefix(), Some(Prefix(b"")));
1218 assert_eq!(name.local_name(), LocalName(b"foo"));
1219 assert_eq!(name.decompose(), (LocalName(b"foo"), Some(Prefix(b""))));
1220
1221 let name = QName(b"foo:bus:baz");
1222 assert_eq!(name.prefix(), Some(Prefix(b"foo")));
1223 assert_eq!(name.local_name(), LocalName(b"bus:baz"));
1224 assert_eq!(
1225 name.decompose(),
1226 (LocalName(b"bus:baz"), Some(Prefix(b"foo")))
1227 );
1228 }
1229}