Coverage Report

Created: 2025-08-26 06:41

/rust/registry/src/index.crates.io-6f17d22bba15001f/quick-xml-0.29.0/src/name.rs
Line
Count
Source (jump to first uncovered line)
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
6
use crate::errors::{Error, Result};
7
use crate::events::attributes::Attribute;
8
use crate::events::BytesStart;
9
use crate::utils::write_byte_string;
10
use memchr::memchr;
11
use std::convert::TryFrom;
12
use 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))]
20
pub struct QName<'a>(pub &'a [u8]);
21
impl<'a> QName<'a> {
22
    /// Converts this name to an internal slice representation.
23
    #[inline(always)]
24
28.6M
    pub fn into_inner(self) -> &'a [u8] {
25
28.6M
        self.0
26
28.6M
    }
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
0
    pub fn local_name(&self) -> LocalName<'a> {
44
0
        LocalName(self.index().map_or(self.0, |i| &self.0[i + 1..]))
45
0
    }
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
0
    pub fn prefix(&self) -> Option<Prefix<'a>> {
62
0
        self.index().map(|i| Prefix(&self.0[..i]))
63
0
    }
64
65
    /// The same as `(qname.local_name(), qname.prefix())`, but does only one
66
    /// lookup for a `':'` symbol.
67
0
    pub fn decompose(&self) -> (LocalName<'a>, Option<Prefix<'a>>) {
68
0
        match self.index() {
69
0
            None => (LocalName(self.0), None),
70
0
            Some(i) => (LocalName(&self.0[i + 1..]), Some(Prefix(&self.0[..i]))),
71
        }
72
0
    }
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
0
    pub fn as_namespace_binding(&self) -> Option<PrefixDeclaration<'a>> {
99
0
        if self.0.starts_with(b"xmlns") {
100
0
            return match self.0.get(5) {
101
0
                None => Some(PrefixDeclaration::Default),
102
0
                Some(&b':') => Some(PrefixDeclaration::Named(&self.0[6..])),
103
0
                _ => None,
104
            };
105
0
        }
106
0
        None
107
0
    }
108
109
    /// Returns the index in the name where prefix ended
110
    #[inline(always)]
111
0
    fn index(&self) -> Option<usize> {
112
0
        memchr(b':', self.0)
113
0
    }
114
}
115
impl<'a> Debug for QName<'a> {
116
0
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
117
0
        write!(f, "QName(")?;
118
0
        write_byte_string(f, self.0)?;
119
0
        write!(f, ")")
120
0
    }
121
}
122
impl<'a> AsRef<[u8]> for QName<'a> {
123
    #[inline]
124
54.3M
    fn as_ref(&self) -> &[u8] {
125
54.3M
        self.0
126
54.3M
    }
<quick_xml::name::QName as core::convert::AsRef<[u8]>>::as_ref
Line
Count
Source
124
47.5M
    fn as_ref(&self) -> &[u8] {
125
47.5M
        self.0
126
47.5M
    }
<quick_xml::name::QName as core::convert::AsRef<[u8]>>::as_ref
Line
Count
Source
124
6.78M
    fn as_ref(&self) -> &[u8] {
125
6.78M
        self.0
126
6.78M
    }
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))]
137
pub struct LocalName<'a>(&'a [u8]);
138
impl<'a> LocalName<'a> {
139
    /// Converts this name to an internal slice representation.
140
    #[inline(always)]
141
0
    pub fn into_inner(self) -> &'a [u8] {
142
0
        self.0
143
0
    }
144
}
145
impl<'a> Debug for LocalName<'a> {
146
0
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
147
0
        write!(f, "LocalName(")?;
148
0
        write_byte_string(f, self.0)?;
149
0
        write!(f, ")")
150
0
    }
151
}
152
impl<'a> AsRef<[u8]> for LocalName<'a> {
153
    #[inline]
154
0
    fn as_ref(&self) -> &[u8] {
155
0
        self.0
156
0
    }
157
}
158
impl<'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
0
    fn from(name: QName<'a>) -> Self {
174
0
        Self(name.index().map_or(name.0, |i| &name.0[i + 1..]))
175
0
    }
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))]
187
pub struct Prefix<'a>(&'a [u8]);
188
impl<'a> Prefix<'a> {
189
    /// Extracts internal slice
190
    #[inline(always)]
191
0
    pub fn into_inner(self) -> &'a [u8] {
192
0
        self.0
193
0
    }
194
}
195
impl<'a> Debug for Prefix<'a> {
196
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
197
0
        write!(f, "Prefix(")?;
198
0
        write_byte_string(f, self.0)?;
199
0
        write!(f, ")")
200
0
    }
201
}
202
impl<'a> AsRef<[u8]> for Prefix<'a> {
203
    #[inline]
204
0
    fn as_ref(&self) -> &[u8] {
205
0
        self.0
206
0
    }
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)]
214
pub 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))]
229
pub struct Namespace<'a>(pub &'a [u8]);
230
impl<'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
0
    pub fn into_inner(self) -> &'a [u8] {
257
0
        self.0
258
0
    }
259
    //TODO: implement value normalization and use it when comparing namespaces
260
}
261
impl<'a> Debug for Namespace<'a> {
262
0
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
263
0
        write!(f, "Namespace(")?;
264
0
        write_byte_string(f, self.0)?;
265
0
        write!(f, ")")
266
0
    }
267
}
268
impl<'a> AsRef<[u8]> for Namespace<'a> {
269
    #[inline]
270
0
    fn as_ref(&self) -> &[u8] {
271
0
        self.0
272
0
    }
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)]
287
pub 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
}
296
impl<'ns> Debug for ResolveResult<'ns> {
297
0
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
298
0
        match self {
299
0
            Self::Unbound => write!(f, "Unbound"),
300
0
            Self::Bound(ns) => write!(f, "Bound({:?})", ns),
301
0
            Self::Unknown(p) => {
302
0
                write!(f, "Unknown(")?;
303
0
                write_byte_string(f, p)?;
304
0
                write!(f, ")")
305
            }
306
        }
307
0
    }
308
}
309
310
impl<'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
0
    fn try_from(result: ResolveResult<'ns>) -> Result<Self> {
316
        use ResolveResult::*;
317
318
0
        match result {
319
0
            Unbound => Ok(None),
320
0
            Bound(ns) => Ok(Some(ns)),
321
0
            Unknown(p) => Err(Error::UnknownPrefix(p)),
322
        }
323
0
    }
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)]
339
struct 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
363
impl 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
0
    fn prefix<'b>(&self, ns_buffer: &'b [u8]) -> Option<Prefix<'b>> {
368
0
        if self.prefix_len == 0 {
369
0
            None
370
        } else {
371
0
            Some(Prefix(&ns_buffer[self.start..self.start + self.prefix_len]))
372
        }
373
0
    }
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
0
    fn namespace<'ns>(&self, buffer: &'ns [u8]) -> ResolveResult<'ns> {
381
0
        if self.value_len == 0 {
382
0
            ResolveResult::Unbound
383
        } else {
384
0
            let start = self.start + self.prefix_len;
385
0
            ResolveResult::Bound(Namespace(&buffer[start..start + self.value_len]))
386
        }
387
0
    }
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)]
394
pub(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
402
impl 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
0
    pub fn push(&mut self, start: &BytesStart, buffer: &mut Vec<u8>) {
408
0
        self.nesting_level += 1;
409
0
        let level = self.nesting_level;
410
        // adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns'
411
        // (default namespace) attribute.
412
0
        for a in start.attributes().with_checks(false) {
413
0
            if let Ok(Attribute { key: k, value: v }) = a {
414
0
                match k.as_namespace_binding() {
415
0
                    Some(PrefixDeclaration::Default) => {
416
0
                        let start = buffer.len();
417
0
                        buffer.extend_from_slice(&v);
418
0
                        self.bindings.push(NamespaceEntry {
419
0
                            start,
420
0
                            prefix_len: 0,
421
0
                            value_len: v.len(),
422
0
                            level,
423
0
                        });
424
0
                    }
425
0
                    Some(PrefixDeclaration::Named(prefix)) => {
426
0
                        let start = buffer.len();
427
0
                        buffer.extend_from_slice(prefix);
428
0
                        buffer.extend_from_slice(&v);
429
0
                        self.bindings.push(NamespaceEntry {
430
0
                            start,
431
0
                            prefix_len: prefix.len(),
432
0
                            value_len: v.len(),
433
0
                            level,
434
0
                        });
435
0
                    }
436
0
                    None => {}
437
                }
438
            } else {
439
0
                break;
440
            }
441
        }
442
0
    }
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
0
    pub fn pop(&mut self, buffer: &mut Vec<u8>) {
449
0
        self.nesting_level -= 1;
450
0
        let current_level = self.nesting_level;
451
0
        // from the back (most deeply nested scope), look for the first scope that is still valid
452
0
        match self.bindings.iter().rposition(|n| n.level <= current_level) {
453
            // none of the namespaces are valid, remove all of them
454
0
            None => {
455
0
                buffer.clear();
456
0
                self.bindings.clear();
457
0
            }
458
            // drop all namespaces past the last valid namespace
459
0
            Some(last_valid_pos) => {
460
0
                if let Some(len) = self.bindings.get(last_valid_pos + 1).map(|n| n.start) {
461
0
                    buffer.truncate(len);
462
0
                    self.bindings.truncate(last_valid_pos + 1);
463
0
                }
464
            }
465
        }
466
0
    }
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
0
    pub fn resolve<'n, 'ns>(
484
0
        &self,
485
0
        name: QName<'n>,
486
0
        buffer: &'ns [u8],
487
0
        use_default: bool,
488
0
    ) -> (ResolveResult<'ns>, LocalName<'n>) {
489
0
        let (local_name, prefix) = name.decompose();
490
0
        (self.resolve_prefix(prefix, buffer, use_default), local_name)
491
0
    }
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
0
    pub fn find<'ns>(&self, element_name: QName, buffer: &'ns [u8]) -> ResolveResult<'ns> {
509
0
        self.resolve_prefix(element_name.prefix(), buffer, true)
510
0
    }
511
512
0
    fn resolve_prefix<'ns>(
513
0
        &self,
514
0
        prefix: Option<Prefix>,
515
0
        buffer: &'ns [u8],
516
0
        use_default: bool,
517
0
    ) -> ResolveResult<'ns> {
518
0
        self.bindings
519
0
            .iter()
520
0
            // Find the last defined binding that corresponds to the given prefix
521
0
            .rev()
522
0
            .find_map(|n| match (n.prefix(buffer), prefix) {
523
                // This is default namespace definition and name has no explicit prefix
524
0
                (None, None) if use_default => Some(n.namespace(buffer)),
525
0
                (None, None) => Some(ResolveResult::Unbound),
526
527
                // One part has prefix but other is not -> skip
528
0
                (None, Some(_)) => None,
529
0
                (Some(_), None) => None,
530
531
                // Prefixes does not match -> skip
532
0
                (Some(definition), Some(usage)) if definition != usage => None,
533
534
                // Prefixes the same, entry defines binding reset (corresponds to `xmlns:p=""`)
535
0
                _ if n.value_len == 0 => Some(Self::maybe_unknown(prefix)),
536
                // Prefixes the same, returns corresponding namespace
537
0
                _ => Some(n.namespace(buffer)),
538
0
            })
539
0
            .unwrap_or_else(|| Self::maybe_unknown(prefix))
540
0
    }
541
542
    #[inline]
543
0
    fn maybe_unknown(prefix: Option<Prefix>) -> ResolveResult<'static> {
544
0
        match prefix {
545
0
            Some(p) => ResolveResult::Unknown(p.into_inner().to_vec()),
546
0
            None => ResolveResult::Unbound,
547
        }
548
0
    }
549
}
550
551
#[cfg(test)]
552
mod 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
}