Skip to content

Commit

Permalink
Add reserved namespace bindings.
Browse files Browse the repository at this point in the history
This adds xml and xmlns namespace bindings. These are defined at
https://www.w3.org/TR/xml-names11/#xmlReserved.
  • Loading branch information
wt committed Aug 15, 2023
1 parent f957002 commit d0d94eb
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

### New Features

- [#545]: resolve well-known namespaces to their approrpriate URIs

### Bug Fixes

### Misc Changes
Expand Down
82 changes: 81 additions & 1 deletion src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,24 @@ pub(crate) struct NamespaceResolver {
nesting_level: i32,
}

/// These constants define the reserved namespaces for the xml standard.
///
/// The prefix `xml` is by definition bound to the namespace name
/// `http://www.w3.org/XML/1998/namespace`. It may, but need not, be declared, and must not be
/// undeclared or bound to any other namespace name. Other prefixes must not be bound to this
/// namespace name, and it must not be declared as the default namespace.
///
/// The prefix `xmlns` is used only to declare namespace bindings and is by definition bound
/// to the namespace name http://www.w3.org/2000/xmlns/. It must not be declared or
/// undeclared. Other prefixes must not be bound to this namespace name, and it must not be
/// declared as the default namespace. Element names must not have the prefix xmlns.
///
/// [reserved namespaces]: https://www.w3.org/TR/xml-names11/#xmlReserved
static WELL_KNOWN_NAMESPACES: &'static [[&str; 2]] = &[
["xml", "http://www.w3.org/XML/1998/namespace"],
["xmlns", "http://www.w3.org/2000/xmlns/"]
];

impl NamespaceResolver {
/// Begins a new scope and add to it all [namespace bindings] that found in
/// the specified start element.
Expand Down Expand Up @@ -542,7 +560,12 @@ impl NamespaceResolver {
#[inline]
fn maybe_unknown(prefix: Option<Prefix>) -> ResolveResult<'static> {
match prefix {
Some(p) => ResolveResult::Unknown(p.into_inner().to_vec()),
Some(p) => {
WELL_KNOWN_NAMESPACES.iter().find(|x| {p == Prefix(x[0].as_bytes())}).map_or_else(
|| ResolveResult::Unknown(p.into_inner().to_vec()),
|[_, uri]| ResolveResult::Bound(Namespace(uri.as_bytes())),
)
},
None => ResolveResult::Unbound,
}
}
Expand Down Expand Up @@ -787,6 +810,63 @@ mod namespaces {
}
}

mod builtin_prefixes {
use super::*;
use pretty_assertions::assert_eq;

#[test]
fn undeclared_reserved_prefix_xml() {
let prefix_name = "xml";
let namespace_uri = "http://www.w3.org/XML/1998/namespace";

let prefix = Prefix(prefix_name.as_bytes());
let namespace = Namespace(namespace_uri.as_bytes());

let resolver = NamespaceResolver::default();
let tag = b"random";

let name_buf = [prefix.into_inner(), tag].join(&b":"[..]);
let name = QName(&name_buf);

assert_eq!(
resolver.resolve(name, b"", true),
(Bound(namespace), LocalName(tag))
);

assert_eq!(
resolver.resolve(name.clone(), b"", false),
(Bound(namespace), LocalName(tag))
);
assert_eq!(resolver.find(name.clone(), b""), Bound(namespace));
}

#[test]
fn undeclared_reserved_prefix_xmlns() {
let prefix_name = "xmlns";
let namespace_uri = "http://www.w3.org/2000/xmlns/";

let prefix = Prefix(prefix_name.as_bytes());
let namespace = Namespace(namespace_uri.as_bytes());

let resolver = NamespaceResolver::default();
let tag = b"random";

let name_buf = [prefix.into_inner(), tag].join(&b":"[..]);
let name = QName(&name_buf);

assert_eq!(
resolver.resolve(name, b"", true),
(Bound(namespace), LocalName(tag))
);

assert_eq!(
resolver.resolve(name.clone(), b"", false),
(Bound(namespace), LocalName(tag))
);
assert_eq!(resolver.find(name.clone(), b""), Bound(namespace));
}
}

#[test]
fn undeclared_prefix() {
let name = QName(b"unknown:prefix");
Expand Down

0 comments on commit d0d94eb

Please sign in to comment.