Skip to content

Commit 7855788

Browse files
committed
Add reserved namespace bindings.
This adds xml and xmlns namespace bindings. These are defined at https://www.w3.org/TR/xml-names11/#xmlReserved.
1 parent f957002 commit 7855788

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
### New Features
1414

15+
- [#545]: resolve well-known namespaces to their approrpriate URIs
16+
1517
### Bug Fixes
1618

1719
### Misc Changes

src/name.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,24 @@ pub(crate) struct NamespaceResolver {
399399
nesting_level: i32,
400400
}
401401

402+
/// These constants define the reserved namespaces for the xml standard.
403+
///
404+
/// The prefix `xml` is by definition bound to the namespace name
405+
/// `http://www.w3.org/XML/1998/namespace`. It may, but need not, be declared, and must not be
406+
/// undeclared or bound to any other namespace name. Other prefixes must not be bound to this
407+
/// namespace name, and it must not be declared as the default namespace.
408+
///
409+
/// The prefix `xmlns` is used only to declare namespace bindings and is by definition bound
410+
/// to the namespace name http://www.w3.org/2000/xmlns/. It must not be declared or
411+
/// undeclared. Other prefixes must not be bound to this namespace name, and it must not be
412+
/// declared as the default namespace. Element names must not have the prefix xmlns.
413+
///
414+
/// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
415+
static WELL_KNOWN_NAMESPACES: &'static [[&str; 2]] = &[
416+
["xml", "http://www.w3.org/XML/1998/namespace"],
417+
["xmlns", "http://www.w3.org/2000/xmlns/"],
418+
];
419+
402420
impl NamespaceResolver {
403421
/// Begins a new scope and add to it all [namespace bindings] that found in
404422
/// the specified start element.
@@ -542,7 +560,13 @@ impl NamespaceResolver {
542560
#[inline]
543561
fn maybe_unknown(prefix: Option<Prefix>) -> ResolveResult<'static> {
544562
match prefix {
545-
Some(p) => ResolveResult::Unknown(p.into_inner().to_vec()),
563+
Some(p) => WELL_KNOWN_NAMESPACES
564+
.iter()
565+
.find(|x| p == Prefix(x[0].as_bytes()))
566+
.map_or_else(
567+
|| ResolveResult::Unknown(p.into_inner().to_vec()),
568+
|[_, uri]| ResolveResult::Bound(Namespace(uri.as_bytes())),
569+
),
546570
None => ResolveResult::Unbound,
547571
}
548572
}
@@ -787,6 +811,63 @@ mod namespaces {
787811
}
788812
}
789813

814+
mod builtin_prefixes {
815+
use super::*;
816+
use pretty_assertions::assert_eq;
817+
818+
#[test]
819+
fn undeclared_reserved_prefix_xml() {
820+
let prefix_name = "xml";
821+
let namespace_uri = "http://www.w3.org/XML/1998/namespace";
822+
823+
let prefix = Prefix(prefix_name.as_bytes());
824+
let namespace = Namespace(namespace_uri.as_bytes());
825+
826+
let resolver = NamespaceResolver::default();
827+
let tag = b"random";
828+
829+
let name_buf = [prefix.into_inner(), tag].join(&b":"[..]);
830+
let name = QName(&name_buf);
831+
832+
assert_eq!(
833+
resolver.resolve(name, b"", true),
834+
(Bound(namespace), LocalName(tag))
835+
);
836+
837+
assert_eq!(
838+
resolver.resolve(name.clone(), b"", false),
839+
(Bound(namespace), LocalName(tag))
840+
);
841+
assert_eq!(resolver.find(name.clone(), b""), Bound(namespace));
842+
}
843+
844+
#[test]
845+
fn undeclared_reserved_prefix_xmlns() {
846+
let prefix_name = "xmlns";
847+
let namespace_uri = "http://www.w3.org/2000/xmlns/";
848+
849+
let prefix = Prefix(prefix_name.as_bytes());
850+
let namespace = Namespace(namespace_uri.as_bytes());
851+
852+
let resolver = NamespaceResolver::default();
853+
let tag = b"random";
854+
855+
let name_buf = [prefix.into_inner(), tag].join(&b":"[..]);
856+
let name = QName(&name_buf);
857+
858+
assert_eq!(
859+
resolver.resolve(name, b"", true),
860+
(Bound(namespace), LocalName(tag))
861+
);
862+
863+
assert_eq!(
864+
resolver.resolve(name.clone(), b"", false),
865+
(Bound(namespace), LocalName(tag))
866+
);
867+
assert_eq!(resolver.find(name.clone(), b""), Bound(namespace));
868+
}
869+
}
870+
790871
#[test]
791872
fn undeclared_prefix() {
792873
let name = QName(b"unknown:prefix");

0 commit comments

Comments
 (0)