diff --git a/xsd-parser-types/src/xml/element.rs b/xsd-parser-types/src/xml/element.rs
index a6143397..e35025a8 100644
--- a/xsd-parser-types/src/xml/element.rs
+++ b/xsd-parser-types/src/xml/element.rs
@@ -10,7 +10,7 @@ use quick_xml::{
name::QName,
};
-use crate::misc::format_utf8_slice;
+use crate::misc::{format_utf8_slice, Namespace, NamespacePrefix};
#[cfg(feature = "quick-xml")]
use crate::quick_xml::{
@@ -93,6 +93,29 @@ impl<'a> Element<'a> {
self
}
+
+ /// Add a namespace to the namespace context of this element.
+ ///
+ /// This will not add a namespace attribute to the element itself. It only
+ /// tells the serializer that this namespace must be valid in the context of
+ /// this element. If the namespace is not already declared in a parent element,
+ /// a suitable `xmlns` attribute will be added automatically.
+ ///
+ /// If you want to add a namespace declaration attribute to the element in
+ /// any case, use the [`Element::attribute`] method instead.
+ #[must_use]
+ pub fn namespace
(mut self, prefix: P, namespace: N) -> Self
+ where
+ P: Into>,
+ N: Into>,
+ {
+ let mut namespaces = self.namespaces.into_owned();
+ namespaces.insert(prefix.into().into(), namespace.into().into());
+
+ self.namespaces = namespaces.into_shared();
+
+ self
+ }
}
impl Debug for Element<'_> {
@@ -172,6 +195,7 @@ impl<'ser, 'el> ElementSerializer<'ser, 'el> {
Self::Start { name, element }
}
+ #[allow(clippy::too_many_lines)]
fn next_item(&mut self, helper: &mut SerializeHelper) -> Result>, Error> {
loop {
match replace(self, Self::Done) {
@@ -183,9 +207,19 @@ impl<'ser, 'el> ElementSerializer<'ser, 'el> {
});
let mut start = BytesStart::new(element_name);
+
+ helper.begin_ns_scope();
+ for (prefix, ns) in &**element.namespaces {
+ let prefix = NamespacePrefix::new(prefix.0.clone().into_owned());
+ let ns = Namespace::new(ns.0.clone().into_owned());
+ helper.write_xmlns(&mut start, Some(&prefix), &ns);
+ }
+
start.extend_attributes(attributes);
let event = if element.values.is_empty() {
+ helper.end_ns_scope();
+
Event::Empty(start)
} else {
let values = element.values.iter();
@@ -206,6 +240,8 @@ impl<'ser, 'el> ElementSerializer<'ser, 'el> {
let end = BytesEnd::new(element_name);
let event = Event::End(end);
+ helper.end_ns_scope();
+
return Ok(Some(event));
}
Self::NextValue {
diff --git a/xsd-parser-types/src/xml/namespaces.rs b/xsd-parser-types/src/xml/namespaces.rs
index a0663c5f..f651a298 100644
--- a/xsd-parser-types/src/xml/namespaces.rs
+++ b/xsd-parser-types/src/xml/namespaces.rs
@@ -12,12 +12,18 @@ use crate::misc::format_utf8_slice;
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Namespaces<'a>(pub HashMap, Value<'a>>);
-impl Namespaces<'_> {
+impl<'a> Namespaces<'a> {
/// Create a new [`Namespaces`] instance.
#[must_use]
pub fn new() -> Self {
Self::default()
}
+
+ /// Convert this list into a shared version ([`NamespacesShared`]).
+ #[must_use]
+ pub fn into_shared(self) -> NamespacesShared<'a> {
+ NamespacesShared::new(self)
+ }
}
impl<'a> Deref for Namespaces<'a> {
@@ -81,6 +87,12 @@ impl<'a> From<&'a [u8]> for Key<'a> {
}
}
+impl<'a> From> for Key<'a> {
+ fn from(value: Cow<'a, [u8]>) -> Self {
+ Self(value)
+ }
+}
+
impl Deref for Key<'_> {
type Target = [u8];
@@ -146,6 +158,24 @@ impl Borrow<[u8]> for Value<'_> {
}
}
+impl From> for Value<'static> {
+ fn from(value: Vec) -> Self {
+ Self(Cow::Owned(value))
+ }
+}
+
+impl<'a> From<&'a [u8]> for Value<'a> {
+ fn from(value: &'a [u8]) -> Self {
+ Self(Cow::Borrowed(value))
+ }
+}
+
+impl<'a> From> for Value<'a> {
+ fn from(value: Cow<'a, [u8]>) -> Self {
+ Self(value)
+ }
+}
+
/// Represents a shared list of namespaces.
///
/// This is useful to not store the same map again and again. Is uses an [`Arc`]
diff --git a/xsd-parser/tests/feature/any/example/default.xml b/xsd-parser/tests/feature/any/example/default.xml
index d0a6d14e..9af45ddc 100644
--- a/xsd-parser/tests/feature/any/example/default.xml
+++ b/xsd-parser/tests/feature/any/example/default.xml
@@ -6,7 +6,7 @@
def
-
+
diff --git a/xsd-parser/tests/feature/any/mod.rs b/xsd-parser/tests/feature/any/mod.rs
index e8d5072d..966e2ecf 100644
--- a/xsd-parser/tests/feature/any/mod.rs
+++ b/xsd-parser/tests/feature/any/mod.rs
@@ -80,7 +80,12 @@ macro_rules! test_obj {
},
ChoiceType {
any_attribute: AnyAttributes::default(),
- content: ChoiceTypeContent::Any(Element::default().name(b"AnyElement2")),
+ content: ChoiceTypeContent::Any(
+ Element::default()
+ .name(b"AnyElement2")
+ .namespace(b"tns", b"http://example.com")
+ .namespace(b"anyNs", b"http://example.com/anyNs"),
+ ),
},
ChoiceType {
any_attribute: AnyAttributes::default(),