Skip to content

Commit 816b064

Browse files
committed
ns: Use QName API when doing tests for matching namespace entry
1 parent c2209f1 commit 816b064

File tree

1 file changed

+65
-6
lines changed

1 file changed

+65
-6
lines changed

src/name.rs

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,52 @@ impl<'a> QName<'a> {
2323
self.0
2424
}
2525

26+
/// Returns local part of this qualified name.
27+
///
28+
/// All content up to and including the first `:` character is removed from
29+
/// the tag name.
30+
///
31+
/// # Examples
32+
///
33+
/// ```
34+
/// # use quick_xml::name::QName;
35+
/// let simple = QName(b"simple-name");
36+
/// assert_eq!(simple.local_name().as_ref(), b"simple-name");
37+
///
38+
/// let qname = QName(b"namespace:simple-name");
39+
/// assert_eq!(qname.local_name().as_ref(), b"simple-name");
40+
/// ```
41+
pub fn local_name(&self) -> LocalName<'a> {
42+
LocalName(self.index().map_or(self.0, |i| &self.0[i + 1..]))
43+
}
44+
45+
/// Returns namespace part of this qualified name or `None` if namespace part
46+
/// is not defined (symbol `':'` not found).
47+
///
48+
/// # Examples
49+
///
50+
/// ```
51+
/// # use std::convert::AsRef;
52+
/// # use quick_xml::name::QName;
53+
/// let simple = QName(b"simple-name");
54+
/// assert_eq!(simple.prefix(), None);
55+
///
56+
/// let qname = QName(b"prefix:simple-name");
57+
/// assert_eq!(qname.prefix().as_ref().map(|n| n.as_ref()), Some(b"prefix".as_ref()));
58+
/// ```
59+
pub fn prefix(&self) -> Option<Prefix<'a>> {
60+
self.index().map(|i| Prefix(&self.0[..i]))
61+
}
62+
63+
/// The same as `(qname.local_name(), qname.prefix())`, but does only one
64+
/// lookup for a `':'` symbol.
65+
pub fn decompose(&self) -> (LocalName<'a>, Option<Prefix<'a>>) {
66+
match self.index() {
67+
None => (LocalName(self.0), None),
68+
Some(i) => (LocalName(&self.0[i + 1..]), Some(Prefix(&self.0[..i]))),
69+
}
70+
}
71+
2672
/// Returns the index in the name where prefix ended
2773
#[inline(always)]
2874
fn index(&self) -> Option<usize> {
@@ -214,6 +260,17 @@ struct NamespaceEntry {
214260
}
215261

216262
impl NamespaceEntry {
263+
/// Get the namespace prefix, bound to this namespace declaration, or `None`,
264+
/// if this declaration is for default namespace (`xmlns="..."`).
265+
#[inline]
266+
fn prefix<'b>(&self, ns_buffer: &'b [u8]) -> Option<Prefix<'b>> {
267+
if self.prefix_len == 0 {
268+
None
269+
} else {
270+
Some(Prefix(&ns_buffer[self.start..self.start + self.prefix_len]))
271+
}
272+
}
273+
217274
/// Gets the namespace name (the URI) slice out of namespace buffer
218275
///
219276
/// Returns `None` if namespace for this prefix was explicitly removed from
@@ -231,12 +288,14 @@ impl NamespaceEntry {
231288
/// Check if the namespace matches the potentially qualified name
232289
#[inline]
233290
fn is_match(&self, buffer: &[u8], name: QName) -> bool {
234-
let qname = name.into_inner();
235-
if self.prefix_len == 0 {
236-
!qname.contains(&b':')
237-
} else {
238-
qname.get(self.prefix_len).map_or(false, |n| *n == b':')
239-
&& qname.starts_with(&buffer[self.start..self.start + self.prefix_len])
291+
match (self.prefix(buffer), name.prefix()) {
292+
// If both parts has no prefixes -> matched
293+
(None, None) => true,
294+
// If one part has prefix but other is not -> not matched
295+
(None, Some(_)) => false,
296+
(Some(_), None) => false,
297+
// Otherwise check that prefixes the same
298+
(Some(definition), Some(usage)) => definition == usage,
240299
}
241300
}
242301
}

0 commit comments

Comments
 (0)