/rust/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs
Line | Count | Source |
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::events::attributes::Attribute; |
7 | | use crate::events::{BytesStart, Event}; |
8 | | use crate::utils::write_byte_string; |
9 | | use memchr::memchr; |
10 | | use std::fmt::{self, Debug, Formatter}; |
11 | | use std::iter::FusedIterator; |
12 | | |
13 | | /// Some namespace was invalid |
14 | | #[derive(Debug, Clone, PartialEq, Eq)] |
15 | | pub enum NamespaceError { |
16 | | /// Specified namespace prefix is unknown, cannot resolve namespace for it |
17 | | UnknownPrefix(Vec<u8>), |
18 | | /// Attempts to bind the `xml` prefix to something other than `http://www.w3.org/XML/1998/namespace`. |
19 | | /// |
20 | | /// `xml` prefix can be bound only to `http://www.w3.org/XML/1998/namespace`. |
21 | | /// |
22 | | /// Contains the namespace to which `xml` tried to be bound. |
23 | | InvalidXmlPrefixBind(Vec<u8>), |
24 | | /// Attempts to bind the `xmlns` prefix. |
25 | | /// |
26 | | /// `xmlns` prefix is always bound to `http://www.w3.org/2000/xmlns/` and cannot be bound |
27 | | /// to any other namespace or even to `http://www.w3.org/2000/xmlns/`. |
28 | | /// |
29 | | /// Contains the namespace to which `xmlns` tried to be bound. |
30 | | InvalidXmlnsPrefixBind(Vec<u8>), |
31 | | /// Attempts to bind some prefix (except `xml`) to `http://www.w3.org/XML/1998/namespace`. |
32 | | /// |
33 | | /// Only `xml` prefix can be bound to `http://www.w3.org/XML/1998/namespace`. |
34 | | /// |
35 | | /// Contains the prefix that is tried to be bound. |
36 | | InvalidPrefixForXml(Vec<u8>), |
37 | | /// Attempts to bind some prefix to `http://www.w3.org/2000/xmlns/`. |
38 | | /// |
39 | | /// `http://www.w3.org/2000/xmlns/` cannot be bound to any prefix, even to `xmlns`. |
40 | | /// |
41 | | /// Contains the prefix that is tried to be bound. |
42 | | InvalidPrefixForXmlns(Vec<u8>), |
43 | | } |
44 | | |
45 | | impl fmt::Display for NamespaceError { |
46 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
47 | 0 | match self { |
48 | 0 | Self::UnknownPrefix(prefix) => { |
49 | 0 | f.write_str("unknown namespace prefix '")?; |
50 | 0 | write_byte_string(f, prefix)?; |
51 | 0 | f.write_str("'") |
52 | | } |
53 | 0 | Self::InvalidXmlPrefixBind(namespace) => { |
54 | 0 | f.write_str("the namespace prefix 'xml' cannot be bound to '")?; |
55 | 0 | write_byte_string(f, namespace)?; |
56 | 0 | f.write_str("'") |
57 | | } |
58 | 0 | Self::InvalidXmlnsPrefixBind(namespace) => { |
59 | 0 | f.write_str("the namespace prefix 'xmlns' cannot be bound to '")?; |
60 | 0 | write_byte_string(f, namespace)?; |
61 | 0 | f.write_str("'") |
62 | | } |
63 | 0 | Self::InvalidPrefixForXml(prefix) => { |
64 | 0 | f.write_str("the namespace prefix '")?; |
65 | 0 | write_byte_string(f, prefix)?; |
66 | 0 | f.write_str("' cannot be bound to 'http://www.w3.org/XML/1998/namespace'") |
67 | | } |
68 | 0 | Self::InvalidPrefixForXmlns(prefix) => { |
69 | 0 | f.write_str("the namespace prefix '")?; |
70 | 0 | write_byte_string(f, prefix)?; |
71 | 0 | f.write_str("' cannot be bound to 'http://www.w3.org/2000/xmlns/'") |
72 | | } |
73 | | } |
74 | 0 | } |
75 | | } |
76 | | |
77 | | impl std::error::Error for NamespaceError {} |
78 | | |
79 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
80 | | |
81 | | /// A [qualified name] of an element or an attribute, including an optional |
82 | | /// namespace [prefix](Prefix) and a [local name](LocalName). |
83 | | /// |
84 | | /// [qualified name]: https://www.w3.org/TR/xml-names11/#dt-qualname |
85 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
86 | | #[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))] |
87 | | pub struct QName<'a>(pub &'a [u8]); |
88 | | impl<'a> QName<'a> { |
89 | | /// Converts this name to an internal slice representation. |
90 | | #[inline(always)] |
91 | 0 | pub const fn into_inner(self) -> &'a [u8] { |
92 | 0 | self.0 |
93 | 0 | } |
94 | | |
95 | | /// Returns local part of this qualified name. |
96 | | /// |
97 | | /// All content up to and including the first `:` character is removed from |
98 | | /// the tag name. |
99 | | /// |
100 | | /// # Examples |
101 | | /// |
102 | | /// ``` |
103 | | /// # use quick_xml::name::QName; |
104 | | /// let simple = QName(b"simple-name"); |
105 | | /// assert_eq!(simple.local_name().as_ref(), b"simple-name"); |
106 | | /// |
107 | | /// let qname = QName(b"namespace:simple-name"); |
108 | | /// assert_eq!(qname.local_name().as_ref(), b"simple-name"); |
109 | | /// ``` |
110 | 0 | pub fn local_name(&self) -> LocalName<'a> { |
111 | 0 | LocalName(self.index().map_or(self.0, |i| &self.0[i + 1..])) |
112 | 0 | } |
113 | | |
114 | | /// Returns namespace part of this qualified name or `None` if namespace part |
115 | | /// is not defined (symbol `':'` not found). |
116 | | /// |
117 | | /// # Examples |
118 | | /// |
119 | | /// ``` |
120 | | /// # use std::convert::AsRef; |
121 | | /// # use quick_xml::name::QName; |
122 | | /// let simple = QName(b"simple-name"); |
123 | | /// assert_eq!(simple.prefix(), None); |
124 | | /// |
125 | | /// let qname = QName(b"prefix:simple-name"); |
126 | | /// assert_eq!(qname.prefix().as_ref().map(|n| n.as_ref()), Some(b"prefix".as_ref())); |
127 | | /// ``` |
128 | 0 | pub fn prefix(&self) -> Option<Prefix<'a>> { |
129 | 0 | self.index().map(|i| Prefix(&self.0[..i])) |
130 | 0 | } |
131 | | |
132 | | /// The same as `(qname.local_name(), qname.prefix())`, but does only one |
133 | | /// lookup for a `':'` symbol. |
134 | 0 | pub fn decompose(&self) -> (LocalName<'a>, Option<Prefix<'a>>) { |
135 | 0 | match self.index() { |
136 | 0 | None => (LocalName(self.0), None), |
137 | 0 | Some(i) => (LocalName(&self.0[i + 1..]), Some(Prefix(&self.0[..i]))), |
138 | | } |
139 | 0 | } |
140 | | |
141 | | /// If that `QName` represents `"xmlns"` series of names, returns `Some`, |
142 | | /// otherwise `None` is returned. |
143 | | /// |
144 | | /// # Examples |
145 | | /// |
146 | | /// ``` |
147 | | /// # use quick_xml::name::{QName, PrefixDeclaration}; |
148 | | /// let qname = QName(b"xmlns"); |
149 | | /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Default)); |
150 | | /// |
151 | | /// let qname = QName(b"xmlns:prefix"); |
152 | | /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b"prefix"))); |
153 | | /// |
154 | | /// // Be aware that this method does not check the validity of the prefix - it can be empty! |
155 | | /// let qname = QName(b"xmlns:"); |
156 | | /// assert_eq!(qname.as_namespace_binding(), Some(PrefixDeclaration::Named(b""))); |
157 | | /// |
158 | | /// let qname = QName(b"other-name"); |
159 | | /// assert_eq!(qname.as_namespace_binding(), None); |
160 | | /// |
161 | | /// // https://www.w3.org/TR/xml-names11/#xmlReserved |
162 | | /// let qname = QName(b"xmlns-reserved-name"); |
163 | | /// assert_eq!(qname.as_namespace_binding(), None); |
164 | | /// ``` |
165 | 0 | pub fn as_namespace_binding(&self) -> Option<PrefixDeclaration<'a>> { |
166 | 0 | if self.0.starts_with(b"xmlns") { |
167 | 0 | return match self.0.get(5) { |
168 | 0 | None => Some(PrefixDeclaration::Default), |
169 | 0 | Some(&b':') => Some(PrefixDeclaration::Named(&self.0[6..])), |
170 | 0 | _ => None, |
171 | | }; |
172 | 0 | } |
173 | 0 | None |
174 | 0 | } |
175 | | |
176 | | /// Returns the index in the name where prefix ended |
177 | | #[inline(always)] |
178 | 0 | fn index(&self) -> Option<usize> { |
179 | 0 | memchr(b':', self.0) |
180 | 0 | } |
181 | | } |
182 | | impl<'a> Debug for QName<'a> { |
183 | 0 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
184 | 0 | write!(f, "QName(")?; |
185 | 0 | write_byte_string(f, self.0)?; |
186 | 0 | write!(f, ")") |
187 | 0 | } |
188 | | } |
189 | | impl<'a> AsRef<[u8]> for QName<'a> { |
190 | | #[inline] |
191 | 0 | fn as_ref(&self) -> &[u8] { |
192 | 0 | self.0 |
193 | 0 | } |
194 | | } |
195 | | |
196 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
197 | | |
198 | | /// A [local (unqualified) name] of an element or an attribute, i.e. a name |
199 | | /// without [prefix](Prefix). |
200 | | /// |
201 | | /// [local (unqualified) name]: https://www.w3.org/TR/xml-names11/#dt-localname |
202 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
203 | | #[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))] |
204 | | pub struct LocalName<'a>(pub(crate) &'a [u8]); |
205 | | impl<'a> LocalName<'a> { |
206 | | /// Converts this name to an internal slice representation. |
207 | | #[inline(always)] |
208 | 0 | pub const fn into_inner(self) -> &'a [u8] { |
209 | 0 | self.0 |
210 | 0 | } |
211 | | } |
212 | | impl<'a> Debug for LocalName<'a> { |
213 | 0 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
214 | 0 | write!(f, "LocalName(")?; |
215 | 0 | write_byte_string(f, self.0)?; |
216 | 0 | write!(f, ")") |
217 | 0 | } |
218 | | } |
219 | | impl<'a> AsRef<[u8]> for LocalName<'a> { |
220 | | #[inline] |
221 | 0 | fn as_ref(&self) -> &[u8] { |
222 | 0 | self.0 |
223 | 0 | } |
224 | | } |
225 | | impl<'a> From<QName<'a>> for LocalName<'a> { |
226 | | /// Creates `LocalName` from a [`QName`] |
227 | | /// |
228 | | /// # Examples |
229 | | /// |
230 | | /// ``` |
231 | | /// # use quick_xml::name::{LocalName, QName}; |
232 | | /// |
233 | | /// let local: LocalName = QName(b"unprefixed").into(); |
234 | | /// assert_eq!(local.as_ref(), b"unprefixed"); |
235 | | /// |
236 | | /// let local: LocalName = QName(b"some:prefix").into(); |
237 | | /// assert_eq!(local.as_ref(), b"prefix"); |
238 | | /// ``` |
239 | | #[inline] |
240 | 0 | fn from(name: QName<'a>) -> Self { |
241 | 0 | Self(name.index().map_or(name.0, |i| &name.0[i + 1..])) |
242 | 0 | } |
243 | | } |
244 | | |
245 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
246 | | |
247 | | /// A [namespace prefix] part of the [qualified name](QName) of an element tag |
248 | | /// or an attribute: a `prefix` in `<prefix:local-element-name>` or |
249 | | /// `prefix:local-attribute-name="attribute value"`. |
250 | | /// |
251 | | /// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix |
252 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
253 | | #[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))] |
254 | | pub struct Prefix<'a>(&'a [u8]); |
255 | | impl<'a> Prefix<'a> { |
256 | | /// Extracts internal slice |
257 | | #[inline(always)] |
258 | 0 | pub const fn into_inner(self) -> &'a [u8] { |
259 | 0 | self.0 |
260 | 0 | } |
261 | | |
262 | | /// Checks if this prefix is a special prefix `xml`. |
263 | | #[inline(always)] |
264 | 0 | pub const fn is_xml(&self) -> bool { |
265 | 0 | matches!(self.0, b"xml") |
266 | 0 | } |
267 | | |
268 | | /// Checks if this prefix is a special prefix `xmlns`. |
269 | | #[inline(always)] |
270 | 0 | pub const fn is_xmlns(&self) -> bool { |
271 | 0 | matches!(self.0, b"xmlns") |
272 | 0 | } |
273 | | } |
274 | | impl<'a> Debug for Prefix<'a> { |
275 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
276 | 0 | write!(f, "Prefix(")?; |
277 | 0 | write_byte_string(f, self.0)?; |
278 | 0 | write!(f, ")") |
279 | 0 | } |
280 | | } |
281 | | impl<'a> AsRef<[u8]> for Prefix<'a> { |
282 | | #[inline] |
283 | 0 | fn as_ref(&self) -> &[u8] { |
284 | 0 | self.0 |
285 | 0 | } |
286 | | } |
287 | | |
288 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
289 | | |
290 | | /// A namespace prefix declaration, `xmlns` or `xmlns:<name>`, as defined in |
291 | | /// [XML Schema specification](https://www.w3.org/TR/xml-names11/#ns-decl) |
292 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
293 | | pub enum PrefixDeclaration<'a> { |
294 | | /// XML attribute binds a default namespace. Corresponds to `xmlns` in `xmlns="..."` |
295 | | Default, |
296 | | /// XML attribute binds a specified prefix to a namespace. Corresponds to a |
297 | | /// `prefix` in `xmlns:prefix="..."`, which is stored as payload of this variant. |
298 | | Named(&'a [u8]), |
299 | | } |
300 | | impl<'a> Debug for PrefixDeclaration<'a> { |
301 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
302 | 0 | match self { |
303 | 0 | Self::Default => f.write_str("PrefixDeclaration::Default"), |
304 | 0 | Self::Named(prefix) => { |
305 | 0 | f.write_str("PrefixDeclaration::Named(")?; |
306 | 0 | write_byte_string(f, prefix)?; |
307 | 0 | f.write_str(")") |
308 | | } |
309 | | } |
310 | 0 | } |
311 | | } |
312 | | |
313 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
314 | | |
315 | | /// A [namespace name] that is declared in a `xmlns[:prefix]="namespace name"`. |
316 | | /// |
317 | | /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName |
318 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
319 | | #[cfg_attr(feature = "serde-types", derive(serde::Deserialize, serde::Serialize))] |
320 | | pub struct Namespace<'a>(pub &'a [u8]); |
321 | | impl<'a> Namespace<'a> { |
322 | | /// Converts this namespace to an internal slice representation. |
323 | | /// |
324 | | /// This is [non-normalized] attribute value, i.e. any entity references is |
325 | | /// not expanded and space characters are not removed. This means, that |
326 | | /// different byte slices, returned from this method, can represent the same |
327 | | /// namespace and would be treated by parser as identical. |
328 | | /// |
329 | | /// For example, if the entity **eacute** has been defined to be **é**, |
330 | | /// the empty tags below all contain namespace declarations binding the |
331 | | /// prefix `p` to the same [IRI reference], `http://example.org/rosé`. |
332 | | /// |
333 | | /// ```xml |
334 | | /// <p:foo xmlns:p="http://example.org/rosé" /> |
335 | | /// <p:foo xmlns:p="http://example.org/rosé" /> |
336 | | /// <p:foo xmlns:p="http://example.org/rosé" /> |
337 | | /// <p:foo xmlns:p="http://example.org/rosé" /> |
338 | | /// <p:foo xmlns:p="http://example.org/rosé" /> |
339 | | /// ``` |
340 | | /// |
341 | | /// This is because XML entity references are expanded during attribute value |
342 | | /// normalization. |
343 | | /// |
344 | | /// [non-normalized]: https://www.w3.org/TR/xml11/#AVNormalize |
345 | | /// [IRI reference]: https://datatracker.ietf.org/doc/html/rfc3987 |
346 | | #[inline(always)] |
347 | 0 | pub const fn into_inner(self) -> &'a [u8] { |
348 | 0 | self.0 |
349 | 0 | } |
350 | | //TODO: implement value normalization and use it when comparing namespaces |
351 | | } |
352 | | impl<'a> Debug for Namespace<'a> { |
353 | 0 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
354 | 0 | write!(f, "Namespace(")?; |
355 | 0 | write_byte_string(f, self.0)?; |
356 | 0 | write!(f, ")") |
357 | 0 | } |
358 | | } |
359 | | impl<'a> AsRef<[u8]> for Namespace<'a> { |
360 | | #[inline] |
361 | 0 | fn as_ref(&self) -> &[u8] { |
362 | 0 | self.0 |
363 | 0 | } |
364 | | } |
365 | | |
366 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
367 | | |
368 | | /// Result of [prefix] resolution which creates by [`NamespaceResolver::resolve`], [`NsReader::resolve_attribute`], |
369 | | /// [`NsReader::resolve_element`], [`NsReader::read_resolved_event`] and |
370 | | /// [`NsReader::read_resolved_event_into`] methods. |
371 | | /// |
372 | | /// [prefix]: Prefix |
373 | | /// [`NsReader::resolve_attribute`]: crate::reader::NsReader::resolve_attribute |
374 | | /// [`NsReader::resolve_element`]: crate::reader::NsReader::resolve_element |
375 | | /// [`NsReader::read_resolved_event`]: crate::reader::NsReader::read_resolved_event |
376 | | /// [`NsReader::read_resolved_event_into`]: crate::reader::NsReader::read_resolved_event_into |
377 | | #[derive(Clone, PartialEq, Eq, Hash)] |
378 | | pub enum ResolveResult<'ns> { |
379 | | /// Qualified name does not contain prefix, and resolver does not define |
380 | | /// default namespace, so name is not bound to any namespace |
381 | | Unbound, |
382 | | /// [`Prefix`] resolved to the specified namespace |
383 | | Bound(Namespace<'ns>), |
384 | | /// Specified prefix was not found in scope |
385 | | Unknown(Vec<u8>), |
386 | | } |
387 | | impl<'ns> Debug for ResolveResult<'ns> { |
388 | 0 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
389 | 0 | match self { |
390 | 0 | Self::Unbound => write!(f, "Unbound"), |
391 | 0 | Self::Bound(ns) => write!(f, "Bound({:?})", ns), |
392 | 0 | Self::Unknown(p) => { |
393 | 0 | write!(f, "Unknown(")?; |
394 | 0 | write_byte_string(f, p)?; |
395 | 0 | write!(f, ")") |
396 | | } |
397 | | } |
398 | 0 | } |
399 | | } |
400 | | |
401 | | impl<'ns> TryFrom<ResolveResult<'ns>> for Option<Namespace<'ns>> { |
402 | | type Error = NamespaceError; |
403 | | |
404 | | /// Try to convert this result to an optional namespace and returns |
405 | | /// [`NamespaceError::UnknownPrefix`] if this result represents unknown prefix |
406 | 0 | fn try_from(result: ResolveResult<'ns>) -> Result<Self, NamespaceError> { |
407 | | use ResolveResult::*; |
408 | | |
409 | 0 | match result { |
410 | 0 | Unbound => Ok(None), |
411 | 0 | Bound(ns) => Ok(Some(ns)), |
412 | 0 | Unknown(p) => Err(NamespaceError::UnknownPrefix(p)), |
413 | | } |
414 | 0 | } |
415 | | } |
416 | | |
417 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
418 | | |
419 | | /// An entry that contains index into the buffer with namespace bindings. |
420 | | /// |
421 | | /// Defines a mapping from *[namespace prefix]* to *[namespace name]*. |
422 | | /// If prefix is empty, defines a *default namespace* binding that applies to |
423 | | /// unprefixed element names (unprefixed attribute names do not bind to any |
424 | | /// namespace and they processing is dependent on the element in which their |
425 | | /// defined). |
426 | | /// |
427 | | /// [namespace prefix]: https://www.w3.org/TR/xml-names11/#dt-prefix |
428 | | /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName |
429 | | #[derive(Debug, Clone)] |
430 | | struct NamespaceBinding { |
431 | | /// Index of the namespace in the buffer |
432 | | start: usize, |
433 | | /// Length of the prefix |
434 | | /// * if greater than zero, then binds this namespace to the slice |
435 | | /// `[start..start + prefix_len]` in the buffer. |
436 | | /// * else defines the current default namespace. |
437 | | prefix_len: usize, |
438 | | /// The length of a namespace name (the URI) of this namespace declaration. |
439 | | /// Name started just after prefix and extend for `value_len` bytes. |
440 | | /// |
441 | | /// The XML standard [specifies] that an empty namespace value 'removes' a namespace declaration |
442 | | /// for the extent of its scope. For prefix declarations that's not very interesting, but it is |
443 | | /// vital for default namespace declarations. With `xmlns=""` you can revert back to the default |
444 | | /// behaviour of leaving unqualified element names unqualified. |
445 | | /// |
446 | | /// [specifies]: https://www.w3.org/TR/xml-names11/#scoping |
447 | | value_len: usize, |
448 | | /// Level of nesting at which this namespace was declared. The declaring element is included, |
449 | | /// i.e., a declaration on the document root has `level = 1`. |
450 | | /// This is used to pop the namespace when the element gets closed. |
451 | | level: u16, |
452 | | } |
453 | | |
454 | | impl NamespaceBinding { |
455 | | /// Get the namespace prefix, bound to this namespace declaration, or `None`, |
456 | | /// if this declaration is for default namespace (`xmlns="..."`). |
457 | | #[inline] |
458 | 0 | fn prefix<'b>(&self, ns_buffer: &'b [u8]) -> Option<Prefix<'b>> { |
459 | 0 | if self.prefix_len == 0 { |
460 | 0 | None |
461 | | } else { |
462 | 0 | Some(Prefix(&ns_buffer[self.start..self.start + self.prefix_len])) |
463 | | } |
464 | 0 | } |
465 | | |
466 | | /// Gets the namespace name (the URI) slice out of namespace buffer |
467 | | /// |
468 | | /// Returns `None` if namespace for this prefix was explicitly removed from |
469 | | /// scope, using `xmlns[:prefix]=""` |
470 | | #[inline] |
471 | 0 | fn namespace<'ns>(&self, buffer: &'ns [u8]) -> ResolveResult<'ns> { |
472 | 0 | if self.value_len == 0 { |
473 | 0 | ResolveResult::Unbound |
474 | | } else { |
475 | 0 | let start = self.start + self.prefix_len; |
476 | 0 | ResolveResult::Bound(Namespace(&buffer[start..start + self.value_len])) |
477 | | } |
478 | 0 | } |
479 | | } |
480 | | |
481 | | /// A storage for currently defined namespace bindings, which is used to resolve |
482 | | /// prefixes into namespaces. |
483 | | /// |
484 | | /// Holds all internal logic to push/pop namespaces with their levels. |
485 | | #[derive(Debug, Clone)] |
486 | | pub struct NamespaceResolver { |
487 | | /// Buffer that contains names of namespace prefixes (the part between `xmlns:` |
488 | | /// and an `=`) and namespace values. |
489 | | buffer: Vec<u8>, |
490 | | /// A stack of namespace bindings to prefixes that currently in scope |
491 | | bindings: Vec<NamespaceBinding>, |
492 | | /// The number of open tags at the moment. We need to keep track of this to know which namespace |
493 | | /// declarations to remove when we encounter an `End` event. |
494 | | nesting_level: u16, |
495 | | } |
496 | | |
497 | | /// That constant define the one of [reserved namespaces] for the xml standard. |
498 | | /// |
499 | | /// The prefix `xml` is by definition bound to the namespace name |
500 | | /// `http://www.w3.org/XML/1998/namespace`. It may, but need not, be declared, and must not be |
501 | | /// undeclared or bound to any other namespace name. Other prefixes must not be bound to this |
502 | | /// namespace name, and it must not be declared as the default namespace. |
503 | | /// |
504 | | /// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved |
505 | | const RESERVED_NAMESPACE_XML: (Prefix, Namespace) = ( |
506 | | Prefix(b"xml"), |
507 | | Namespace(b"http://www.w3.org/XML/1998/namespace"), |
508 | | ); |
509 | | /// That constant define the one of [reserved namespaces] for the xml standard. |
510 | | /// |
511 | | /// The prefix `xmlns` is used only to declare namespace bindings and is by definition bound |
512 | | /// to the namespace name `http://www.w3.org/2000/xmlns/`. It must not be declared or |
513 | | /// undeclared. Other prefixes must not be bound to this namespace name, and it must not be |
514 | | /// declared as the default namespace. Element names must not have the prefix `xmlns`. |
515 | | /// |
516 | | /// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved |
517 | | const RESERVED_NAMESPACE_XMLNS: (Prefix, Namespace) = ( |
518 | | Prefix(b"xmlns"), |
519 | | Namespace(b"http://www.w3.org/2000/xmlns/"), |
520 | | ); |
521 | | |
522 | | impl Default for NamespaceResolver { |
523 | 0 | fn default() -> Self { |
524 | 0 | let mut buffer = Vec::new(); |
525 | 0 | let mut bindings = Vec::new(); |
526 | 0 | for ent in &[RESERVED_NAMESPACE_XML, RESERVED_NAMESPACE_XMLNS] { |
527 | 0 | let prefix = ent.0.into_inner(); |
528 | 0 | let uri = ent.1.into_inner(); |
529 | 0 | bindings.push(NamespaceBinding { |
530 | 0 | start: buffer.len(), |
531 | 0 | prefix_len: prefix.len(), |
532 | 0 | value_len: uri.len(), |
533 | 0 | level: 0, |
534 | 0 | }); |
535 | 0 | buffer.extend(prefix); |
536 | 0 | buffer.extend(uri); |
537 | 0 | } |
538 | | |
539 | 0 | Self { |
540 | 0 | buffer, |
541 | 0 | bindings, |
542 | 0 | nesting_level: 0, |
543 | 0 | } |
544 | 0 | } |
545 | | } |
546 | | |
547 | | impl NamespaceResolver { |
548 | | /// Adds new binding of prefix to namespace, returns the result of operation. |
549 | | /// |
550 | | /// Binding will be added on current nesting level and will be removed, when |
551 | | /// level will be [popped out]. |
552 | | /// |
553 | | /// The operation may fail if you try to (re-)declare reserved prefixes `xml` and `xmlns`. |
554 | | /// |
555 | | /// Note, that method does not check if namespace was already added on that level. |
556 | | /// Use `resolver.bindings_of(resolver.level()).any()` if you want to check that. |
557 | | /// New definition will be added and replace the old. |
558 | | /// |
559 | | /// Implementation detail: memory occupied by old binding of that level still will be used. |
560 | | /// |
561 | | /// ``` |
562 | | /// # use pretty_assertions::assert_eq; |
563 | | /// # use quick_xml::name::{Namespace, NamespaceResolver, PrefixDeclaration, QName, ResolveResult}; |
564 | | /// # |
565 | | /// let mut resolver = NamespaceResolver::default(); |
566 | | /// // names without prefix are unbound by default |
567 | | /// assert_eq!( |
568 | | /// resolver.resolve_element(QName(b"name")).0, |
569 | | /// ResolveResult::Unbound, |
570 | | /// ); |
571 | | /// // names with undeclared prefix are unknown |
572 | | /// assert_eq!( |
573 | | /// resolver.resolve_element(QName(b"ns:name")).0, |
574 | | /// ResolveResult::Unknown(b"ns".to_vec()), |
575 | | /// ); |
576 | | /// |
577 | | /// resolver.add(PrefixDeclaration::Default, Namespace(b"example.com")); |
578 | | /// resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b"my:namespace")); |
579 | | /// |
580 | | /// assert_eq!( |
581 | | /// resolver.resolve_element(QName(b"name")).0, |
582 | | /// ResolveResult::Bound(Namespace(b"example.com")), |
583 | | /// ); |
584 | | /// assert_eq!( |
585 | | /// resolver.resolve_element(QName(b"ns:name")).0, |
586 | | /// ResolveResult::Bound(Namespace(b"my:namespace")), |
587 | | /// ); |
588 | | /// |
589 | | /// // adding empty namespace clears the binding |
590 | | /// resolver.add(PrefixDeclaration::Default, Namespace(b"")); |
591 | | /// resolver.add(PrefixDeclaration::Named(b"ns"), Namespace(b"")); |
592 | | /// |
593 | | /// assert_eq!( |
594 | | /// resolver.resolve_element(QName(b"name")).0, |
595 | | /// ResolveResult::Unbound, |
596 | | /// ); |
597 | | /// assert_eq!( |
598 | | /// resolver.resolve_element(QName(b"ns:name")).0, |
599 | | /// ResolveResult::Unknown(b"ns".to_vec()), |
600 | | /// ); |
601 | | /// ``` |
602 | | /// [popped out]: Self::pop |
603 | 0 | pub fn add( |
604 | 0 | &mut self, |
605 | 0 | prefix: PrefixDeclaration, |
606 | 0 | namespace: Namespace, |
607 | 0 | ) -> Result<(), NamespaceError> { |
608 | 0 | let level = self.nesting_level; |
609 | 0 | match prefix { |
610 | 0 | PrefixDeclaration::Default => { |
611 | 0 | let start = self.buffer.len(); |
612 | 0 | self.buffer.extend_from_slice(namespace.0); |
613 | 0 | self.bindings.push(NamespaceBinding { |
614 | 0 | start, |
615 | 0 | prefix_len: 0, |
616 | 0 | value_len: namespace.0.len(), |
617 | 0 | level, |
618 | 0 | }); |
619 | 0 | } |
620 | 0 | PrefixDeclaration::Named(b"xml") => { |
621 | 0 | if namespace != RESERVED_NAMESPACE_XML.1 { |
622 | | // error, `xml` prefix explicitly set to different value |
623 | 0 | return Err(NamespaceError::InvalidXmlPrefixBind(namespace.0.to_vec())); |
624 | 0 | } |
625 | | // don't add another NamespaceEntry for the `xml` namespace prefix |
626 | | } |
627 | 0 | PrefixDeclaration::Named(b"xmlns") => { |
628 | | // error, `xmlns` prefix explicitly set |
629 | 0 | return Err(NamespaceError::InvalidXmlnsPrefixBind(namespace.0.to_vec())); |
630 | | } |
631 | 0 | PrefixDeclaration::Named(prefix) => { |
632 | | // error, non-`xml` prefix set to xml uri |
633 | 0 | if namespace == RESERVED_NAMESPACE_XML.1 { |
634 | 0 | return Err(NamespaceError::InvalidPrefixForXml(prefix.to_vec())); |
635 | | } else |
636 | | // error, non-`xmlns` prefix set to xmlns uri |
637 | 0 | if namespace == RESERVED_NAMESPACE_XMLNS.1 { |
638 | 0 | return Err(NamespaceError::InvalidPrefixForXmlns(prefix.to_vec())); |
639 | 0 | } |
640 | | |
641 | 0 | let start = self.buffer.len(); |
642 | 0 | self.buffer.extend_from_slice(prefix); |
643 | 0 | self.buffer.extend_from_slice(namespace.0); |
644 | 0 | self.bindings.push(NamespaceBinding { |
645 | 0 | start, |
646 | 0 | prefix_len: prefix.len(), |
647 | 0 | value_len: namespace.0.len(), |
648 | 0 | level, |
649 | 0 | }); |
650 | | } |
651 | | } |
652 | 0 | Ok(()) |
653 | 0 | } |
654 | | |
655 | | /// Begins a new scope and add to it all [namespace bindings] that found in |
656 | | /// the specified start element. |
657 | | /// |
658 | | /// [namespace bindings]: https://www.w3.org/TR/xml-names11/#dt-NSDecl |
659 | 0 | pub fn push(&mut self, start: &BytesStart) -> Result<(), NamespaceError> { |
660 | 0 | self.nesting_level += 1; |
661 | | // adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns' |
662 | | // (default namespace) attribute. |
663 | 0 | for a in start.attributes().with_checks(false) { |
664 | 0 | if let Ok(Attribute { key: k, value: v }) = a { |
665 | 0 | if let Some(prefix) = k.as_namespace_binding() { |
666 | 0 | self.add(prefix, Namespace(&v))?; |
667 | 0 | } |
668 | | } else { |
669 | 0 | break; |
670 | | } |
671 | | } |
672 | 0 | Ok(()) |
673 | 0 | } |
674 | | |
675 | | /// Ends a top-most scope by popping all [namespace bindings], that was added by |
676 | | /// last call to [`Self::push()`] and [`Self::add()`]. |
677 | | /// |
678 | | /// [namespace bindings]: https://www.w3.org/TR/xml-names11/#dt-NSDecl |
679 | 0 | pub fn pop(&mut self) { |
680 | 0 | self.nesting_level = self.nesting_level.saturating_sub(1); |
681 | 0 | let current_level = self.nesting_level; |
682 | | // from the back (most deeply nested scope), look for the first scope that is still valid |
683 | 0 | match self.bindings.iter().rposition(|n| n.level <= current_level) { |
684 | | // none of the namespaces are valid, remove all of them |
685 | 0 | None => { |
686 | 0 | self.buffer.clear(); |
687 | 0 | self.bindings.clear(); |
688 | 0 | } |
689 | | // drop all namespaces past the last valid namespace |
690 | 0 | Some(last_valid_pos) => { |
691 | 0 | if let Some(len) = self.bindings.get(last_valid_pos + 1).map(|n| n.start) { |
692 | 0 | self.buffer.truncate(len); |
693 | 0 | self.bindings.truncate(last_valid_pos + 1); |
694 | 0 | } |
695 | | } |
696 | | } |
697 | 0 | } |
698 | | |
699 | | /// Resolves a potentially qualified **element name** or **attribute name** |
700 | | /// into _(namespace name, local name)_. |
701 | | /// |
702 | | /// _Qualified_ names have the form `local-name` or `prefix:local-name` where the `prefix` |
703 | | /// is defined on any containing XML element via `xmlns:prefix="the:namespace:uri"`. |
704 | | /// The namespace prefix can be defined on the same element as the name in question. |
705 | | /// |
706 | | /// The method returns following results depending on the `name` shape, `attribute` flag |
707 | | /// and the presence of the default namespace on element or any of its parents: |
708 | | /// |
709 | | /// |use_default|`xmlns="..."`|QName |ResolveResult |LocalName |
710 | | /// |-----------|-------------|-------------------|-----------------------|------------ |
711 | | /// |`false` |_(any)_ |`local-name` |[`Unbound`] |`local-name` |
712 | | /// |`false` |_(any)_ |`prefix:local-name`|[`Bound`] / [`Unknown`]|`local-name` |
713 | | /// |`true` |Not defined |`local-name` |[`Unbound`] |`local-name` |
714 | | /// |`true` |Defined |`local-name` |[`Bound`] (to `xmlns`) |`local-name` |
715 | | /// |`true` |_(any)_ |`prefix:local-name`|[`Bound`] / [`Unknown`]|`local-name` |
716 | | /// |
717 | | /// # Parameters |
718 | | /// - `name`: probably qualified name to resolve; |
719 | | /// - `use_default`: whether to try to translate `None` prefix to the currently default namespace |
720 | | /// (bound using `xmlns="default namespace"`) or return [`ResolveResult::Unbound`]. |
721 | | /// For attribute names this should be set to `false` and for element names to `true`. |
722 | | /// |
723 | | /// # Lifetimes |
724 | | /// |
725 | | /// - `'n`: lifetime of a name. Returned local name will be bound to the same |
726 | | /// lifetime as the name in question. |
727 | | /// - returned namespace name will be bound to the resolver itself |
728 | | /// |
729 | | /// [`Bound`]: ResolveResult::Bound |
730 | | /// [`Unbound`]: ResolveResult::Unbound |
731 | | /// [`Unknown`]: ResolveResult::Unknown |
732 | | #[inline] |
733 | 0 | pub fn resolve<'n>( |
734 | 0 | &self, |
735 | 0 | name: QName<'n>, |
736 | 0 | use_default: bool, |
737 | 0 | ) -> (ResolveResult<'_>, LocalName<'n>) { |
738 | 0 | let (local_name, prefix) = name.decompose(); |
739 | 0 | (self.resolve_prefix(prefix, use_default), local_name) |
740 | 0 | } |
741 | | |
742 | | /// Convenient method to call `resolve(name, true)`. May be used to clearly |
743 | | /// express that we want to resolve an element name, and not an attribute name. |
744 | | #[inline] |
745 | 0 | pub fn resolve_element<'n>(&self, name: QName<'n>) -> (ResolveResult<'_>, LocalName<'n>) { |
746 | 0 | self.resolve(name, true) |
747 | 0 | } |
748 | | |
749 | | /// Convenient method to call `resolve(name, false)`. May be used to clearly |
750 | | /// express that we want to resolve an attribute name, and not an element name. |
751 | | #[inline] |
752 | 0 | pub fn resolve_attribute<'n>(&self, name: QName<'n>) -> (ResolveResult<'_>, LocalName<'n>) { |
753 | 0 | self.resolve(name, false) |
754 | 0 | } |
755 | | |
756 | | /// Finds a [namespace name] for a given event, if applicable. |
757 | | /// |
758 | | /// Namespace is resolved only for [`Start`], [`Empty`] and [`End`] events. |
759 | | /// For all other events the concept of namespace is not defined, so |
760 | | /// a [`ResolveResult::Unbound`] is returned. |
761 | | /// |
762 | | /// # Examples |
763 | | /// |
764 | | /// ``` |
765 | | /// # use pretty_assertions::assert_eq; |
766 | | /// use quick_xml::events::Event; |
767 | | /// use quick_xml::name::{Namespace, QName, ResolveResult::*}; |
768 | | /// use quick_xml::reader::NsReader; |
769 | | /// |
770 | | /// let mut reader = NsReader::from_str(r#" |
771 | | /// <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test"> |
772 | | /// <y:tag2><!--Test comment-->Test</y:tag2> |
773 | | /// <y:tag2>Test 2</y:tag2> |
774 | | /// </x:tag1> |
775 | | /// "#); |
776 | | /// reader.config_mut().trim_text(true); |
777 | | /// |
778 | | /// let mut count = 0; |
779 | | /// let mut txt = Vec::new(); |
780 | | /// loop { |
781 | | /// let event = reader.read_event().unwrap(); |
782 | | /// match reader.resolver().resolve_event(event) { |
783 | | /// (Bound(Namespace(b"www.xxxx")), Event::Start(e)) => { |
784 | | /// count += 1; |
785 | | /// assert_eq!(e.local_name(), QName(b"tag1").into()); |
786 | | /// } |
787 | | /// (Bound(Namespace(b"www.yyyy")), Event::Start(e)) => { |
788 | | /// count += 1; |
789 | | /// assert_eq!(e.local_name(), QName(b"tag2").into()); |
790 | | /// } |
791 | | /// (_, Event::Start(_)) => unreachable!(), |
792 | | /// |
793 | | /// (_, Event::Text(e)) => { |
794 | | /// txt.push(e.decode().unwrap().into_owned()) |
795 | | /// } |
796 | | /// (_, Event::Eof) => break, |
797 | | /// _ => (), |
798 | | /// } |
799 | | /// } |
800 | | /// assert_eq!(count, 3); |
801 | | /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]); |
802 | | /// ``` |
803 | | /// |
804 | | /// [namespace name]: https://www.w3.org/TR/xml-names11/#dt-NSName |
805 | | /// [`Empty`]: Event::Empty |
806 | | /// [`Start`]: Event::Start |
807 | | /// [`End`]: Event::End |
808 | 0 | pub fn resolve_event<'i>(&self, event: Event<'i>) -> (ResolveResult<'_>, Event<'i>) { |
809 | | use Event::*; |
810 | | |
811 | 0 | match event { |
812 | 0 | Empty(e) => (self.resolve_prefix(e.name().prefix(), true), Empty(e)), |
813 | 0 | Start(e) => (self.resolve_prefix(e.name().prefix(), true), Start(e)), |
814 | 0 | End(e) => (self.resolve_prefix(e.name().prefix(), true), End(e)), |
815 | 0 | e => (ResolveResult::Unbound, e), |
816 | | } |
817 | 0 | } |
818 | | |
819 | | /// Resolves given optional prefix (usually got from [`QName`]) into a corresponding namespace. |
820 | | /// |
821 | | /// # Parameters |
822 | | /// - `prefix`: prefix to resolve, usually result of [`QName::prefix()`]; |
823 | | /// - `use_default`: whether to try to translate `None` prefix to the currently default namespace |
824 | | /// (bound using `xmlns="default namespace"`) or return [`ResolveResult::Unbound`]. |
825 | | /// For attribute names this should be set to `false` and for element names to `true`. |
826 | 0 | pub fn resolve_prefix(&self, prefix: Option<Prefix>, use_default: bool) -> ResolveResult<'_> { |
827 | | // Find the last defined binding that corresponds to the given prefix |
828 | 0 | let mut iter = self.bindings.iter().rev(); |
829 | 0 | match (prefix, use_default) { |
830 | | // Attribute name has no explicit prefix -> Unbound |
831 | 0 | (None, false) => ResolveResult::Unbound, |
832 | | // Element name has no explicit prefix -> find nearest xmlns binding |
833 | 0 | (None, true) => match iter.find(|n| n.prefix_len == 0) { |
834 | 0 | Some(n) => n.namespace(&self.buffer), |
835 | 0 | None => ResolveResult::Unbound, |
836 | | }, |
837 | | // Attribute or element name with explicit prefix |
838 | 0 | (Some(p), _) => match iter.find(|n| n.prefix(&self.buffer) == prefix) { |
839 | 0 | Some(n) if n.value_len != 0 => n.namespace(&self.buffer), |
840 | | // Not found or binding reset (corresponds to `xmlns:p=""`) |
841 | 0 | _ => ResolveResult::Unknown(p.into_inner().to_vec()), |
842 | | }, |
843 | | } |
844 | 0 | } |
845 | | |
846 | | /// Returns all the bindings currently in effect except the default `xml` and `xmlns` bindings. |
847 | | /// |
848 | | /// # Examples |
849 | | /// |
850 | | /// This example shows what results the returned iterator would return after |
851 | | /// reading each event of a simple XML. |
852 | | /// |
853 | | /// ``` |
854 | | /// # use pretty_assertions::assert_eq; |
855 | | /// use quick_xml::name::{Namespace, PrefixDeclaration}; |
856 | | /// use quick_xml::NsReader; |
857 | | /// |
858 | | /// let src = "<root> |
859 | | /// <a xmlns=\"a1\" xmlns:a=\"a2\"> |
860 | | /// <b xmlns=\"b1\" xmlns:b=\"b2\"> |
861 | | /// <c/> |
862 | | /// </b> |
863 | | /// <d/> |
864 | | /// </a> |
865 | | /// </root>"; |
866 | | /// let mut reader = NsReader::from_str(src); |
867 | | /// reader.config_mut().trim_text(true); |
868 | | /// // No bindings at the beginning |
869 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![]); |
870 | | /// |
871 | | /// reader.read_resolved_event()?; // <root> |
872 | | /// // No bindings declared on root |
873 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![]); |
874 | | /// |
875 | | /// reader.read_resolved_event()?; // <a> |
876 | | /// // Two bindings declared on "a" |
877 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![ |
878 | | /// (PrefixDeclaration::Default, Namespace(b"a1")), |
879 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")) |
880 | | /// ]); |
881 | | /// |
882 | | /// reader.read_resolved_event()?; // <b> |
883 | | /// // The default prefix got overridden and new "b" prefix |
884 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![ |
885 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")), |
886 | | /// (PrefixDeclaration::Default, Namespace(b"b1")), |
887 | | /// (PrefixDeclaration::Named(b"b"), Namespace(b"b2")) |
888 | | /// ]); |
889 | | /// |
890 | | /// reader.read_resolved_event()?; // <c/> |
891 | | /// // Still the same |
892 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![ |
893 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")), |
894 | | /// (PrefixDeclaration::Default, Namespace(b"b1")), |
895 | | /// (PrefixDeclaration::Named(b"b"), Namespace(b"b2")) |
896 | | /// ]); |
897 | | /// |
898 | | /// reader.read_resolved_event()?; // </b> |
899 | | /// // Still the same |
900 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![ |
901 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")), |
902 | | /// (PrefixDeclaration::Default, Namespace(b"b1")), |
903 | | /// (PrefixDeclaration::Named(b"b"), Namespace(b"b2")) |
904 | | /// ]); |
905 | | /// |
906 | | /// reader.read_resolved_event()?; // <d/> |
907 | | /// // </b> got closed so back to the bindings declared on <a> |
908 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![ |
909 | | /// (PrefixDeclaration::Default, Namespace(b"a1")), |
910 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")) |
911 | | /// ]); |
912 | | /// |
913 | | /// reader.read_resolved_event()?; // </a> |
914 | | /// // Still the same |
915 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![ |
916 | | /// (PrefixDeclaration::Default, Namespace(b"a1")), |
917 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")) |
918 | | /// ]); |
919 | | /// |
920 | | /// reader.read_resolved_event()?; // </root> |
921 | | /// // <a> got closed |
922 | | /// assert_eq!(reader.resolver().bindings().collect::<Vec<_>>(), vec![]); |
923 | | /// # quick_xml::Result::Ok(()) |
924 | | /// ``` |
925 | | #[inline] |
926 | 0 | pub const fn bindings(&self) -> NamespaceBindingsIter<'_> { |
927 | 0 | NamespaceBindingsIter { |
928 | 0 | resolver: self, |
929 | 0 | // We initialize the cursor to 2 to skip the two default namespaces xml: and xmlns: |
930 | 0 | cursor: 2, |
931 | 0 | } |
932 | 0 | } |
933 | | |
934 | | /// Returns all the bindings on the specified level, including the default |
935 | | /// `xml` and `xmlns` bindings. |
936 | | /// |
937 | | /// # Parameters |
938 | | /// - `level`: the nesting level of an XML tag. The document without tags has |
939 | | /// level 0, at which default bindings are declared. The root tag has level 1 |
940 | | /// and all other tags has levels > 1. If specify level more than [current], the |
941 | | /// empty iterator is returned. |
942 | | /// |
943 | | /// # Examples |
944 | | /// |
945 | | /// This example shows what results the returned iterator would return on each |
946 | | /// level after reaning some events of a simple XML. |
947 | | /// |
948 | | /// ``` |
949 | | /// # use pretty_assertions::assert_eq; |
950 | | /// use quick_xml::name::{Namespace, PrefixDeclaration}; |
951 | | /// use quick_xml::NsReader; |
952 | | /// |
953 | | /// let src = "<root> |
954 | | /// <a xmlns=\"a1\" xmlns:a=\"a2\"> |
955 | | /// <b xmlns=\"b1\" xmlns:b=\"b2\"> |
956 | | /// <c/> |
957 | | /// </b> |
958 | | /// <d/> |
959 | | /// </a> |
960 | | /// </root>"; |
961 | | /// let mut reader = NsReader::from_str(src); |
962 | | /// reader.config_mut().trim_text(true); |
963 | | /// reader.read_resolved_event()?; // <root> |
964 | | /// reader.read_resolved_event()?; // <a> |
965 | | /// reader.read_resolved_event()?; // <b> |
966 | | /// reader.read_resolved_event()?; // <c/> |
967 | | /// |
968 | | /// // Default bindings at the beginning |
969 | | /// assert_eq!(reader.resolver().bindings_of(0).collect::<Vec<_>>(), vec![ |
970 | | /// (PrefixDeclaration::Named(b"xml"), Namespace(b"http://www.w3.org/XML/1998/namespace")), |
971 | | /// (PrefixDeclaration::Named(b"xmlns"), Namespace(b"http://www.w3.org/2000/xmlns/")), |
972 | | /// ]); |
973 | | /// |
974 | | /// // No bindings declared on root |
975 | | /// assert_eq!(reader.resolver().bindings_of(1).collect::<Vec<_>>(), vec![]); |
976 | | /// |
977 | | /// // Two bindings declared on "a" |
978 | | /// assert_eq!(reader.resolver().bindings_of(2).collect::<Vec<_>>(), vec![ |
979 | | /// (PrefixDeclaration::Default, Namespace(b"a1")), |
980 | | /// (PrefixDeclaration::Named(b"a"), Namespace(b"a2")), |
981 | | /// ]); |
982 | | /// |
983 | | /// // Two bindings declared on "b" |
984 | | /// assert_eq!(reader.resolver().bindings_of(3).collect::<Vec<_>>(), vec![ |
985 | | /// (PrefixDeclaration::Default, Namespace(b"b1")), |
986 | | /// (PrefixDeclaration::Named(b"b"), Namespace(b"b2")), |
987 | | /// ]); |
988 | | /// |
989 | | /// // No bindings declared on "c" |
990 | | /// assert_eq!(reader.resolver().bindings_of(4).collect::<Vec<_>>(), vec![]); |
991 | | /// |
992 | | /// // No bindings on non-existent level |
993 | | /// assert_eq!(reader.resolver().bindings_of(5).collect::<Vec<_>>(), vec![]); |
994 | | /// # quick_xml::Result::Ok(()) |
995 | | /// ``` |
996 | | /// |
997 | | /// [current]: Self::level |
998 | 0 | pub const fn bindings_of(&self, level: u16) -> NamespaceBindingsOfLevelIter<'_> { |
999 | 0 | NamespaceBindingsOfLevelIter { |
1000 | 0 | resolver: self, |
1001 | 0 | cursor: 0, |
1002 | 0 | level, |
1003 | 0 | } |
1004 | 0 | } |
1005 | | |
1006 | | /// Returns the number of [`push`] calls that were not followed by [`pop`] calls. |
1007 | | /// |
1008 | | /// Due to use of `u16` for level number the number of nested tags in XML |
1009 | | /// are limited by [`u16::MAX`], but that is enough for any real application. |
1010 | | /// |
1011 | | /// # Example |
1012 | | /// |
1013 | | /// ``` |
1014 | | /// # use pretty_assertions::assert_eq; |
1015 | | /// # use quick_xml::events::BytesStart; |
1016 | | /// # use quick_xml::name::{Namespace, NamespaceResolver, PrefixDeclaration, QName, ResolveResult}; |
1017 | | /// # |
1018 | | /// let mut resolver = NamespaceResolver::default(); |
1019 | | /// |
1020 | | /// assert_eq!(resolver.level(), 0); |
1021 | | /// |
1022 | | /// resolver.push(&BytesStart::new("tag")); |
1023 | | /// assert_eq!(resolver.level(), 1); |
1024 | | /// |
1025 | | /// resolver.pop(); |
1026 | | /// assert_eq!(resolver.level(), 0); |
1027 | | /// |
1028 | | /// // pop from empty resolver does nothing |
1029 | | /// resolver.pop(); |
1030 | | /// assert_eq!(resolver.level(), 0); |
1031 | | /// ``` |
1032 | | /// |
1033 | | /// [`push`]: Self::push |
1034 | | /// [`pop`]: Self::pop |
1035 | 0 | pub const fn level(&self) -> u16 { |
1036 | 0 | self.nesting_level |
1037 | 0 | } |
1038 | | } |
1039 | | |
1040 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
1041 | | |
1042 | | /// Iterator on the current declared namespace bindings. Returns pairs of the _(prefix, namespace)_. |
1043 | | /// |
1044 | | /// See [`NamespaceResolver::bindings`] for documentation. |
1045 | | #[derive(Debug, Clone)] |
1046 | | pub struct NamespaceBindingsIter<'a> { |
1047 | | resolver: &'a NamespaceResolver, |
1048 | | cursor: usize, |
1049 | | } |
1050 | | |
1051 | | impl<'a> Iterator for NamespaceBindingsIter<'a> { |
1052 | | type Item = (PrefixDeclaration<'a>, Namespace<'a>); |
1053 | | |
1054 | 0 | fn next(&mut self) -> Option<(PrefixDeclaration<'a>, Namespace<'a>)> { |
1055 | 0 | while let Some(binding) = self.resolver.bindings.get(self.cursor) { |
1056 | 0 | self.cursor += 1; // We increment for next read |
1057 | | |
1058 | | // We check if the key has not been overridden by having a look |
1059 | | // at the namespaces declared after in the array |
1060 | 0 | let prefix = binding.prefix(&self.resolver.buffer); |
1061 | 0 | if self.resolver.bindings[self.cursor..] |
1062 | 0 | .iter() |
1063 | 0 | .any(|ne| prefix == ne.prefix(&self.resolver.buffer)) |
1064 | | { |
1065 | 0 | continue; // Overridden |
1066 | 0 | } |
1067 | 0 | if let ResolveResult::Bound(namespace) = binding.namespace(&self.resolver.buffer) { |
1068 | 0 | let prefix = match prefix { |
1069 | 0 | Some(Prefix(prefix)) => PrefixDeclaration::Named(prefix), |
1070 | 0 | None => PrefixDeclaration::Default, |
1071 | | }; |
1072 | 0 | return Some((prefix, namespace)); |
1073 | 0 | } |
1074 | | } |
1075 | 0 | None // We have exhausted the array |
1076 | 0 | } |
1077 | | |
1078 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
1079 | | // Real count could be less if some namespaces was overridden |
1080 | 0 | (0, Some(self.resolver.bindings.len() - self.cursor)) |
1081 | 0 | } |
1082 | | } |
1083 | | |
1084 | | impl<'a> FusedIterator for NamespaceBindingsIter<'a> {} |
1085 | | |
1086 | | /// The previous name for [`NamespaceBindingsIter`]. |
1087 | | pub type PrefixIter<'a> = NamespaceBindingsIter<'a>; |
1088 | | |
1089 | | /// Iterator on the declared namespace bindings on specified level. Returns pairs of the _(prefix, namespace)_. |
1090 | | /// |
1091 | | /// See [`NamespaceResolver::bindings_of`] for documentation. |
1092 | | #[derive(Debug, Clone)] |
1093 | | pub struct NamespaceBindingsOfLevelIter<'a> { |
1094 | | resolver: &'a NamespaceResolver, |
1095 | | cursor: usize, |
1096 | | level: u16, |
1097 | | } |
1098 | | |
1099 | | impl<'a> Iterator for NamespaceBindingsOfLevelIter<'a> { |
1100 | | type Item = (PrefixDeclaration<'a>, Namespace<'a>); |
1101 | | |
1102 | 0 | fn next(&mut self) -> Option<(PrefixDeclaration<'a>, Namespace<'a>)> { |
1103 | 0 | while let Some(binding) = self.resolver.bindings.get(self.cursor) { |
1104 | 0 | self.cursor += 1; // We increment for next read |
1105 | 0 | if binding.level < self.level { |
1106 | 0 | continue; |
1107 | 0 | } |
1108 | 0 | if binding.level > self.level { |
1109 | 0 | break; |
1110 | 0 | } |
1111 | | |
1112 | 0 | if let ResolveResult::Bound(namespace) = binding.namespace(&self.resolver.buffer) { |
1113 | 0 | let prefix = match binding.prefix(&self.resolver.buffer) { |
1114 | 0 | Some(Prefix(prefix)) => PrefixDeclaration::Named(prefix), |
1115 | 0 | None => PrefixDeclaration::Default, |
1116 | | }; |
1117 | 0 | return Some((prefix, namespace)); |
1118 | 0 | } |
1119 | | } |
1120 | 0 | None // We have exhausted the array |
1121 | 0 | } |
1122 | | |
1123 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
1124 | | // Real count could be less |
1125 | 0 | (0, Some(self.resolver.bindings.len() - self.cursor)) |
1126 | 0 | } |
1127 | | } |
1128 | | |
1129 | | impl<'a> FusedIterator for NamespaceBindingsOfLevelIter<'a> {} |
1130 | | |
1131 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
1132 | | |
1133 | | #[cfg(test)] |
1134 | | mod namespaces { |
1135 | | use super::*; |
1136 | | use pretty_assertions::assert_eq; |
1137 | | use ResolveResult::*; |
1138 | | |
1139 | | /// Unprefixed attribute names (resolved with `false` flag) never have a namespace |
1140 | | /// according to <https://www.w3.org/TR/xml-names11/#defaulting>: |
1141 | | /// |
1142 | | /// > A default namespace declaration applies to all unprefixed element names |
1143 | | /// > within its scope. Default namespace declarations do not apply directly |
1144 | | /// > to attribute names; the interpretation of unprefixed attributes is |
1145 | | /// > determined by the element on which they appear. |
1146 | | mod unprefixed { |
1147 | | use super::*; |
1148 | | use pretty_assertions::assert_eq; |
1149 | | |
1150 | | /// Basic tests that checks that basic resolver functionality is working |
1151 | | #[test] |
1152 | | fn basic() { |
1153 | | let name = QName(b"simple"); |
1154 | | let ns = Namespace(b"default"); |
1155 | | |
1156 | | let mut resolver = NamespaceResolver::default(); |
1157 | | let s = resolver.buffer.len(); |
1158 | | |
1159 | | resolver |
1160 | | .push(&BytesStart::from_content(" xmlns='default'", 0)) |
1161 | | .unwrap(); |
1162 | | assert_eq!(&resolver.buffer[s..], b"default"); |
1163 | | |
1164 | | // Check that tags without namespaces does not change result |
1165 | | resolver.push(&BytesStart::from_content("", 0)).unwrap(); |
1166 | | assert_eq!(&resolver.buffer[s..], b"default"); |
1167 | | resolver.pop(); |
1168 | | |
1169 | | assert_eq!(&resolver.buffer[s..], b"default"); |
1170 | | assert_eq!( |
1171 | | resolver.resolve(name, true), |
1172 | | (Bound(ns), LocalName(b"simple")) |
1173 | | ); |
1174 | | assert_eq!( |
1175 | | resolver.resolve(name, false), |
1176 | | (Unbound, LocalName(b"simple")) |
1177 | | ); |
1178 | | } |
1179 | | |
1180 | | /// Test adding a second level of namespaces, which replaces the previous binding |
1181 | | #[test] |
1182 | | fn override_namespace() { |
1183 | | let name = QName(b"simple"); |
1184 | | let old_ns = Namespace(b"old"); |
1185 | | let new_ns = Namespace(b"new"); |
1186 | | |
1187 | | let mut resolver = NamespaceResolver::default(); |
1188 | | let s = resolver.buffer.len(); |
1189 | | |
1190 | | resolver |
1191 | | .push(&BytesStart::from_content(" xmlns='old'", 0)) |
1192 | | .unwrap(); |
1193 | | resolver |
1194 | | .push(&BytesStart::from_content(" xmlns='new'", 0)) |
1195 | | .unwrap(); |
1196 | | |
1197 | | assert_eq!(&resolver.buffer[s..], b"oldnew"); |
1198 | | assert_eq!( |
1199 | | resolver.resolve(name, true), |
1200 | | (Bound(new_ns), LocalName(b"simple")) |
1201 | | ); |
1202 | | assert_eq!( |
1203 | | resolver.resolve(name, false), |
1204 | | (Unbound, LocalName(b"simple")) |
1205 | | ); |
1206 | | |
1207 | | resolver.pop(); |
1208 | | assert_eq!(&resolver.buffer[s..], b"old"); |
1209 | | assert_eq!( |
1210 | | resolver.resolve(name, true), |
1211 | | (Bound(old_ns), LocalName(b"simple")) |
1212 | | ); |
1213 | | assert_eq!( |
1214 | | resolver.resolve(name, false), |
1215 | | (Unbound, LocalName(b"simple")) |
1216 | | ); |
1217 | | } |
1218 | | |
1219 | | /// Test adding a second level of namespaces, which reset the previous binding |
1220 | | /// to not bound state by specifying an empty namespace name. |
1221 | | /// |
1222 | | /// See <https://www.w3.org/TR/xml-names11/#scoping> |
1223 | | #[test] |
1224 | | fn reset() { |
1225 | | let name = QName(b"simple"); |
1226 | | let old_ns = Namespace(b"old"); |
1227 | | |
1228 | | let mut resolver = NamespaceResolver::default(); |
1229 | | let s = resolver.buffer.len(); |
1230 | | |
1231 | | resolver |
1232 | | .push(&BytesStart::from_content(" xmlns='old'", 0)) |
1233 | | .unwrap(); |
1234 | | resolver |
1235 | | .push(&BytesStart::from_content(" xmlns=''", 0)) |
1236 | | .unwrap(); |
1237 | | |
1238 | | assert_eq!(&resolver.buffer[s..], b"old"); |
1239 | | assert_eq!( |
1240 | | resolver.resolve(name, true), |
1241 | | (Unbound, LocalName(b"simple")) |
1242 | | ); |
1243 | | assert_eq!( |
1244 | | resolver.resolve(name, false), |
1245 | | (Unbound, LocalName(b"simple")) |
1246 | | ); |
1247 | | |
1248 | | resolver.pop(); |
1249 | | assert_eq!(&resolver.buffer[s..], b"old"); |
1250 | | assert_eq!( |
1251 | | resolver.resolve(name, true), |
1252 | | (Bound(old_ns), LocalName(b"simple")) |
1253 | | ); |
1254 | | assert_eq!( |
1255 | | resolver.resolve(name, false), |
1256 | | (Unbound, LocalName(b"simple")) |
1257 | | ); |
1258 | | } |
1259 | | } |
1260 | | |
1261 | | mod declared_prefix { |
1262 | | use super::*; |
1263 | | use pretty_assertions::assert_eq; |
1264 | | |
1265 | | /// Basic tests that checks that basic resolver functionality is working |
1266 | | #[test] |
1267 | | fn basic() { |
1268 | | let name = QName(b"p:with-declared-prefix"); |
1269 | | let ns = Namespace(b"default"); |
1270 | | |
1271 | | let mut resolver = NamespaceResolver::default(); |
1272 | | let s = resolver.buffer.len(); |
1273 | | |
1274 | | resolver |
1275 | | .push(&BytesStart::from_content(" xmlns:p='default'", 0)) |
1276 | | .unwrap(); |
1277 | | assert_eq!(&resolver.buffer[s..], b"pdefault"); |
1278 | | |
1279 | | // Check that tags without namespaces does not change result |
1280 | | resolver.push(&BytesStart::from_content("", 0)).unwrap(); |
1281 | | assert_eq!(&resolver.buffer[s..], b"pdefault"); |
1282 | | resolver.pop(); |
1283 | | |
1284 | | assert_eq!(&resolver.buffer[s..], b"pdefault"); |
1285 | | assert_eq!( |
1286 | | resolver.resolve(name, true), |
1287 | | (Bound(ns), LocalName(b"with-declared-prefix")) |
1288 | | ); |
1289 | | assert_eq!( |
1290 | | resolver.resolve(name, false), |
1291 | | (Bound(ns), LocalName(b"with-declared-prefix")) |
1292 | | ); |
1293 | | } |
1294 | | |
1295 | | /// Test adding a second level of namespaces, which replaces the previous binding |
1296 | | #[test] |
1297 | | fn override_namespace() { |
1298 | | let name = QName(b"p:with-declared-prefix"); |
1299 | | let old_ns = Namespace(b"old"); |
1300 | | let new_ns = Namespace(b"new"); |
1301 | | |
1302 | | let mut resolver = NamespaceResolver::default(); |
1303 | | let s = resolver.buffer.len(); |
1304 | | |
1305 | | resolver |
1306 | | .push(&BytesStart::from_content(" xmlns:p='old'", 0)) |
1307 | | .unwrap(); |
1308 | | resolver |
1309 | | .push(&BytesStart::from_content(" xmlns:p='new'", 0)) |
1310 | | .unwrap(); |
1311 | | |
1312 | | assert_eq!(&resolver.buffer[s..], b"poldpnew"); |
1313 | | assert_eq!( |
1314 | | resolver.resolve(name, true), |
1315 | | (Bound(new_ns), LocalName(b"with-declared-prefix")) |
1316 | | ); |
1317 | | assert_eq!( |
1318 | | resolver.resolve(name, false), |
1319 | | (Bound(new_ns), LocalName(b"with-declared-prefix")) |
1320 | | ); |
1321 | | |
1322 | | resolver.pop(); |
1323 | | assert_eq!(&resolver.buffer[s..], b"pold"); |
1324 | | assert_eq!( |
1325 | | resolver.resolve(name, true), |
1326 | | (Bound(old_ns), LocalName(b"with-declared-prefix")) |
1327 | | ); |
1328 | | assert_eq!( |
1329 | | resolver.resolve(name, false), |
1330 | | (Bound(old_ns), LocalName(b"with-declared-prefix")) |
1331 | | ); |
1332 | | } |
1333 | | |
1334 | | /// Test adding a second level of namespaces, which reset the previous binding |
1335 | | /// to not bound state by specifying an empty namespace name. |
1336 | | /// |
1337 | | /// See <https://www.w3.org/TR/xml-names11/#scoping> |
1338 | | #[test] |
1339 | | fn reset() { |
1340 | | let name = QName(b"p:with-declared-prefix"); |
1341 | | let old_ns = Namespace(b"old"); |
1342 | | |
1343 | | let mut resolver = NamespaceResolver::default(); |
1344 | | let s = resolver.buffer.len(); |
1345 | | |
1346 | | resolver |
1347 | | .push(&BytesStart::from_content(" xmlns:p='old'", 0)) |
1348 | | .unwrap(); |
1349 | | resolver |
1350 | | .push(&BytesStart::from_content(" xmlns:p=''", 0)) |
1351 | | .unwrap(); |
1352 | | |
1353 | | assert_eq!(&resolver.buffer[s..], b"poldp"); |
1354 | | assert_eq!( |
1355 | | resolver.resolve(name, true), |
1356 | | (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix")) |
1357 | | ); |
1358 | | assert_eq!( |
1359 | | resolver.resolve(name, false), |
1360 | | (Unknown(b"p".to_vec()), LocalName(b"with-declared-prefix")) |
1361 | | ); |
1362 | | |
1363 | | resolver.pop(); |
1364 | | assert_eq!(&resolver.buffer[s..], b"pold"); |
1365 | | assert_eq!( |
1366 | | resolver.resolve(name, true), |
1367 | | (Bound(old_ns), LocalName(b"with-declared-prefix")) |
1368 | | ); |
1369 | | assert_eq!( |
1370 | | resolver.resolve(name, false), |
1371 | | (Bound(old_ns), LocalName(b"with-declared-prefix")) |
1372 | | ); |
1373 | | } |
1374 | | } |
1375 | | |
1376 | | /// Tests for `xml` and `xmlns` built-in prefixes. |
1377 | | /// |
1378 | | /// See <https://www.w3.org/TR/xml-names11/#xmlReserved> |
1379 | | mod builtin_prefixes { |
1380 | | use super::*; |
1381 | | |
1382 | | mod xml { |
1383 | | use super::*; |
1384 | | use pretty_assertions::assert_eq; |
1385 | | |
1386 | | /// `xml` prefix are always defined, it is not required to define it explicitly. |
1387 | | #[test] |
1388 | | fn undeclared() { |
1389 | | let name = QName(b"xml:random"); |
1390 | | let namespace = RESERVED_NAMESPACE_XML.1; |
1391 | | |
1392 | | let resolver = NamespaceResolver::default(); |
1393 | | |
1394 | | assert_eq!( |
1395 | | resolver.resolve(name, true), |
1396 | | (Bound(namespace), LocalName(b"random")) |
1397 | | ); |
1398 | | |
1399 | | assert_eq!( |
1400 | | resolver.resolve(name, false), |
1401 | | (Bound(namespace), LocalName(b"random")) |
1402 | | ); |
1403 | | } |
1404 | | |
1405 | | /// `xml` prefix can be declared but it must be bound to the value |
1406 | | /// `http://www.w3.org/XML/1998/namespace` |
1407 | | #[test] |
1408 | | fn rebound_to_correct_ns() { |
1409 | | let mut resolver = NamespaceResolver::default(); |
1410 | | let s = resolver.buffer.len(); |
1411 | | resolver.push( |
1412 | | &BytesStart::from_content( |
1413 | | " xmlns:xml='http://www.w3.org/XML/1998/namespace'", |
1414 | | 0, |
1415 | | ), |
1416 | | ).expect("`xml` prefix should be possible to bound to `http://www.w3.org/XML/1998/namespace`"); |
1417 | | assert_eq!(&resolver.buffer[s..], b""); |
1418 | | } |
1419 | | |
1420 | | /// `xml` prefix cannot be re-declared to another namespace |
1421 | | #[test] |
1422 | | fn rebound_to_incorrect_ns() { |
1423 | | let mut resolver = NamespaceResolver::default(); |
1424 | | let s = resolver.buffer.len(); |
1425 | | assert_eq!( |
1426 | | resolver.push(&BytesStart::from_content( |
1427 | | " xmlns:xml='not_correct_namespace'", |
1428 | | 0, |
1429 | | )), |
1430 | | Err(NamespaceError::InvalidXmlPrefixBind( |
1431 | | b"not_correct_namespace".to_vec() |
1432 | | )), |
1433 | | ); |
1434 | | assert_eq!(&resolver.buffer[s..], b""); |
1435 | | } |
1436 | | |
1437 | | /// `xml` prefix cannot be unbound |
1438 | | #[test] |
1439 | | fn unbound() { |
1440 | | let mut resolver = NamespaceResolver::default(); |
1441 | | let s = resolver.buffer.len(); |
1442 | | assert_eq!( |
1443 | | resolver.push(&BytesStart::from_content(" xmlns:xml=''", 0)), |
1444 | | Err(NamespaceError::InvalidXmlPrefixBind(b"".to_vec())), |
1445 | | ); |
1446 | | assert_eq!(&resolver.buffer[s..], b""); |
1447 | | } |
1448 | | |
1449 | | /// Other prefix cannot be bound to `xml` namespace |
1450 | | #[test] |
1451 | | fn other_prefix_bound_to_xml_namespace() { |
1452 | | let mut resolver = NamespaceResolver::default(); |
1453 | | let s = resolver.buffer.len(); |
1454 | | assert_eq!( |
1455 | | resolver.push(&BytesStart::from_content( |
1456 | | " xmlns:not_xml='http://www.w3.org/XML/1998/namespace'", |
1457 | | 0, |
1458 | | )), |
1459 | | Err(NamespaceError::InvalidPrefixForXml(b"not_xml".to_vec())), |
1460 | | ); |
1461 | | assert_eq!(&resolver.buffer[s..], b""); |
1462 | | } |
1463 | | } |
1464 | | |
1465 | | mod xmlns { |
1466 | | use super::*; |
1467 | | use pretty_assertions::assert_eq; |
1468 | | |
1469 | | /// `xmlns` prefix are always defined, it is forbidden to define it explicitly |
1470 | | #[test] |
1471 | | fn undeclared() { |
1472 | | let name = QName(b"xmlns:random"); |
1473 | | let namespace = RESERVED_NAMESPACE_XMLNS.1; |
1474 | | |
1475 | | let resolver = NamespaceResolver::default(); |
1476 | | |
1477 | | assert_eq!( |
1478 | | resolver.resolve(name, true), |
1479 | | (Bound(namespace), LocalName(b"random")) |
1480 | | ); |
1481 | | |
1482 | | assert_eq!( |
1483 | | resolver.resolve(name, false), |
1484 | | (Bound(namespace), LocalName(b"random")) |
1485 | | ); |
1486 | | } |
1487 | | |
1488 | | /// `xmlns` prefix cannot be re-declared event to its own namespace |
1489 | | #[test] |
1490 | | fn rebound_to_correct_ns() { |
1491 | | let mut resolver = NamespaceResolver::default(); |
1492 | | let s = resolver.buffer.len(); |
1493 | | assert_eq!( |
1494 | | resolver.push(&BytesStart::from_content( |
1495 | | " xmlns:xmlns='http://www.w3.org/2000/xmlns/'", |
1496 | | 0, |
1497 | | )), |
1498 | | Err(NamespaceError::InvalidXmlnsPrefixBind( |
1499 | | b"http://www.w3.org/2000/xmlns/".to_vec() |
1500 | | )), |
1501 | | ); |
1502 | | assert_eq!(&resolver.buffer[s..], b""); |
1503 | | } |
1504 | | |
1505 | | /// `xmlns` prefix cannot be re-declared |
1506 | | #[test] |
1507 | | fn rebound_to_incorrect_ns() { |
1508 | | let mut resolver = NamespaceResolver::default(); |
1509 | | let s = resolver.buffer.len(); |
1510 | | assert_eq!( |
1511 | | resolver.push(&BytesStart::from_content( |
1512 | | " xmlns:xmlns='not_correct_namespace'", |
1513 | | 0, |
1514 | | )), |
1515 | | Err(NamespaceError::InvalidXmlnsPrefixBind( |
1516 | | b"not_correct_namespace".to_vec() |
1517 | | )), |
1518 | | ); |
1519 | | assert_eq!(&resolver.buffer[s..], b""); |
1520 | | } |
1521 | | |
1522 | | /// `xmlns` prefix cannot be unbound |
1523 | | #[test] |
1524 | | fn unbound() { |
1525 | | let mut resolver = NamespaceResolver::default(); |
1526 | | let s = resolver.buffer.len(); |
1527 | | assert_eq!( |
1528 | | resolver.push(&BytesStart::from_content(" xmlns:xmlns=''", 0)), |
1529 | | Err(NamespaceError::InvalidXmlnsPrefixBind(b"".to_vec())), |
1530 | | ); |
1531 | | assert_eq!(&resolver.buffer[s..], b""); |
1532 | | } |
1533 | | |
1534 | | /// Other prefix cannot be bound to `xmlns` namespace |
1535 | | #[test] |
1536 | | fn other_prefix_bound_to_xmlns_namespace() { |
1537 | | let mut resolver = NamespaceResolver::default(); |
1538 | | let s = resolver.buffer.len(); |
1539 | | assert_eq!( |
1540 | | resolver.push(&BytesStart::from_content( |
1541 | | " xmlns:not_xmlns='http://www.w3.org/2000/xmlns/'", |
1542 | | 0, |
1543 | | )), |
1544 | | Err(NamespaceError::InvalidPrefixForXmlns(b"not_xmlns".to_vec())), |
1545 | | ); |
1546 | | assert_eq!(&resolver.buffer[s..], b""); |
1547 | | } |
1548 | | } |
1549 | | } |
1550 | | |
1551 | | #[test] |
1552 | | fn undeclared_prefix() { |
1553 | | let name = QName(b"unknown:prefix"); |
1554 | | |
1555 | | let resolver = NamespaceResolver::default(); |
1556 | | |
1557 | | assert_eq!( |
1558 | | resolver.buffer, |
1559 | | b"xmlhttp://www.w3.org/XML/1998/namespacexmlnshttp://www.w3.org/2000/xmlns/" |
1560 | | ); |
1561 | | assert_eq!( |
1562 | | resolver.resolve(name, true), |
1563 | | (Unknown(b"unknown".to_vec()), LocalName(b"prefix")) |
1564 | | ); |
1565 | | assert_eq!( |
1566 | | resolver.resolve(name, false), |
1567 | | (Unknown(b"unknown".to_vec()), LocalName(b"prefix")) |
1568 | | ); |
1569 | | } |
1570 | | |
1571 | | /// Checks how the QName is decomposed to a prefix and a local name |
1572 | | #[test] |
1573 | | fn prefix_and_local_name() { |
1574 | | let name = QName(b"foo:bus"); |
1575 | | assert_eq!(name.prefix(), Some(Prefix(b"foo"))); |
1576 | | assert_eq!(name.local_name(), LocalName(b"bus")); |
1577 | | assert_eq!(name.decompose(), (LocalName(b"bus"), Some(Prefix(b"foo")))); |
1578 | | |
1579 | | let name = QName(b"foo:"); |
1580 | | assert_eq!(name.prefix(), Some(Prefix(b"foo"))); |
1581 | | assert_eq!(name.local_name(), LocalName(b"")); |
1582 | | assert_eq!(name.decompose(), (LocalName(b""), Some(Prefix(b"foo")))); |
1583 | | |
1584 | | let name = QName(b":foo"); |
1585 | | assert_eq!(name.prefix(), Some(Prefix(b""))); |
1586 | | assert_eq!(name.local_name(), LocalName(b"foo")); |
1587 | | assert_eq!(name.decompose(), (LocalName(b"foo"), Some(Prefix(b"")))); |
1588 | | |
1589 | | let name = QName(b"foo:bus:baz"); |
1590 | | assert_eq!(name.prefix(), Some(Prefix(b"foo"))); |
1591 | | assert_eq!(name.local_name(), LocalName(b"bus:baz")); |
1592 | | assert_eq!( |
1593 | | name.decompose(), |
1594 | | (LocalName(b"bus:baz"), Some(Prefix(b"foo"))) |
1595 | | ); |
1596 | | } |
1597 | | } |