make namespaces optional

This commit is contained in:
cel 🌸 2024-11-20 15:46:24 +00:00
parent a3dc4e1475
commit 49c8d52f0d
3 changed files with 92 additions and 50 deletions

View File

@ -22,7 +22,7 @@ pub struct NamespaceDeclaration {
// names are qualified, they contain a reference to the namespace (held within the reader/writer) // names are qualified, they contain a reference to the namespace (held within the reader/writer)
#[derive(PartialEq, Eq, Hash, Clone, Debug)] #[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct Name { pub struct Name {
pub namespace: String, pub namespace: Option<String>,
pub local_name: String, pub local_name: String,
} }

View File

@ -312,7 +312,7 @@ impl<R> Reader<R> {
.chain(element_namespace_declarations.iter()) .chain(element_namespace_declarations.iter())
.collect(); .collect();
// element name and default attribute namespace // element name
let element_namespace_declaration; let element_namespace_declaration;
let element_local_name = s_tag.name.local_part().to_string(); let element_local_name = s_tag.name.local_part().to_string();
@ -330,10 +330,8 @@ impl<R> Reader<R> {
} }
} }
let element_default_namespace = element_namespace_declaration let element_default_namespace =
.ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))? element_namespace_declaration.map(|decl| decl.namespace.clone());
.namespace
.clone();
let element_name = Name { let element_name = Name {
namespace: element_default_namespace, namespace: element_default_namespace,
@ -361,20 +359,24 @@ impl<R> Reader<R> {
namespace_declaration.prefix.as_deref() == Some(prefix) namespace_declaration.prefix.as_deref() == Some(prefix)
}); });
} }
None => attribute_namespace_declaration = element_namespace_declaration, None => attribute_namespace_declaration = None,
} }
let name;
if let Some(namespace_declaration) = attribute_namespace_declaration { if let Some(namespace_declaration) = attribute_namespace_declaration {
let name = Name { name = Name {
namespace: namespace_declaration.namespace.clone(), namespace: Some(namespace_declaration.namespace.clone()),
local_name: attribute_local_name, local_name: attribute_local_name,
}; };
let value = value.process()?;
// check for duplicate attribute
if let Some(_value) = attributes.insert(name, value) {
return Err(Error::DuplicateAttribute(q_name.to_string()));
}
} else { } else {
return Err(Error::UnqualifiedNamespace(q_name.to_string())); name = Name {
namespace: None,
local_name: attribute_local_name,
};
}
let value = value.process()?;
// check for duplicate attribute
if let Some(_value) = attributes.insert(name, value) {
return Err(Error::DuplicateAttribute(q_name.to_string()));
} }
} }
@ -415,8 +417,7 @@ impl<R> Reader<R> {
} }
let e_tag_namespace = e_tag_namespace_declaration let e_tag_namespace = e_tag_namespace_declaration
.ok_or_else(|| Error::UnqualifiedNamespace(xml_e_tag.name.to_string()))? .map(|decl| decl.namespace.clone())
.namespace
.clone(); .clone();
let e_tag_name = Name { let e_tag_name = Name {
@ -512,10 +513,8 @@ impl<R> Reader<R> {
} }
} }
let element_default_namespace = element_namespace_declaration let element_default_namespace =
.ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))? element_namespace_declaration.map(|decl| decl.namespace.clone());
.namespace
.clone();
let element_name = Name { let element_name = Name {
namespace: element_default_namespace, namespace: element_default_namespace,
@ -541,10 +540,7 @@ impl<R> Reader<R> {
} }
} }
let e_tag_namespace = e_tag_namespace_declaration let e_tag_namespace = e_tag_namespace_declaration.map(|decl| decl.namespace.clone());
.ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))?
.namespace
.clone();
let e_tag_name = Name { let e_tag_name = Name {
namespace: e_tag_namespace, namespace: e_tag_namespace,
@ -577,20 +573,24 @@ impl<R> Reader<R> {
namespace_declaration.prefix.as_deref() == Some(prefix) namespace_declaration.prefix.as_deref() == Some(prefix)
}); });
} }
None => attribute_namespace_declaration = element_namespace_declaration, None => attribute_namespace_declaration = None,
} }
let name;
if let Some(namespace_declaration) = attribute_namespace_declaration { if let Some(namespace_declaration) = attribute_namespace_declaration {
let name = Name { name = Name {
namespace: namespace_declaration.namespace.clone(), namespace: Some(namespace_declaration.namespace.clone()),
local_name: attribute_local_name, local_name: attribute_local_name,
}; };
let value = value.process()?;
// check for duplicate attribute
if let Some(_value) = attributes.insert(name, value) {
return Err(Error::DuplicateAttribute(q_name.to_string()));
}
} else { } else {
return Err(Error::UnqualifiedNamespace(q_name.to_string())); name = Name {
namespace: None,
local_name: attribute_local_name,
};
}
let value = value.process()?;
// check for duplicate attribute
if let Some(_value) = attributes.insert(name, value) {
return Err(Error::DuplicateAttribute(q_name.to_string()));
} }
} }

View File

@ -23,19 +23,24 @@ impl<W: AsyncWrite + Unpin> Writer<W> {
} }
pub async fn write_start(&mut self, element: Element) -> Result<()> { pub async fn write_start(&mut self, element: Element) -> Result<()> {
let mut namespace_declarations_stack: Vec<_> = self let namespace_declarations_stack: Vec<_> = self
.namespace_declarations .namespace_declarations
.iter() .iter()
.flatten() .flatten()
.chain(&element.namespace_declarations) .chain(&element.namespace_declarations)
.collect(); .collect();
let name_namespace_declaration = namespace_declarations_stack
.iter() let prefix;
.rfind(|namespace_declaration| { if let Some(namespace) = &element.name.namespace {
namespace_declaration.namespace == element.name.namespace let name_namespace_declaration = namespace_declarations_stack
}) .iter()
.ok_or(Error::UndeclaredNamespace(element.name.namespace.clone()))?; .rfind(|namespace_declaration| namespace_declaration.namespace == *namespace)
let prefix = &name_namespace_declaration.prefix; .ok_or(Error::UndeclaredNamespace(namespace.clone()))?;
prefix = name_namespace_declaration.prefix.as_ref();
} else {
prefix = None
}
let name; let name;
if let Some(prefix) = &prefix { if let Some(prefix) = &prefix {
name = xml::QName::PrefixedName(xml::PrefixedName { name = xml::QName::PrefixedName(xml::PrefixedName {
@ -48,8 +53,6 @@ impl<W: AsyncWrite + Unpin> Writer<W> {
)?) )?)
} }
namespace_declarations_stack.push(name_namespace_declaration);
let mut attributes = Vec::new(); let mut attributes = Vec::new();
for namespace_declaration in &element.namespace_declarations { for namespace_declaration in &element.namespace_declarations {
@ -67,6 +70,39 @@ impl<W: AsyncWrite + Unpin> Writer<W> {
attributes.push(xml_attribute); attributes.push(xml_attribute);
} }
for (name, value) in &element.attributes {
let prefix;
if let Some(namespace) = &name.namespace {
let name_namespace_declaration = namespace_declarations_stack
.iter()
.rfind(|namespace_declaration| namespace_declaration.namespace == *namespace)
.ok_or(Error::UndeclaredNamespace(namespace.clone()))?;
prefix = name_namespace_declaration.prefix.as_ref();
} else {
prefix = None
}
let att_name;
if let Some(prefix) = &prefix {
att_name = xml::QName::PrefixedName(xml::PrefixedName {
prefix: xml::Prefix::parse_full(prefix)?,
local_part: xml::LocalPart::parse_full(&element.name.local_name)?,
})
} else {
att_name = xml::QName::UnprefixedName(xml::UnprefixedName::parse_full(
&element.name.local_name,
)?)
}
let value = xml::AttValue::from(value.as_str());
let xml_attribute = xml::Attribute::Attribute {
name: att_name,
value,
};
attributes.push(xml_attribute);
}
let s_tag = xml::STag { name, attributes }; let s_tag = xml::STag { name, attributes };
s_tag.write(&mut self.inner).await?; s_tag.write(&mut self.inner).await?;
@ -82,12 +118,18 @@ impl<W: AsyncWrite + Unpin> Writer<W> {
let e_tag; let e_tag;
let namespace_declarations_stack: Vec<_> = let namespace_declarations_stack: Vec<_> =
self.namespace_declarations.iter().flatten().collect(); self.namespace_declarations.iter().flatten().collect();
let namespace_declaration = namespace_declarations_stack
.iter() let prefix;
.rfind(|namespace_declaration| namespace_declaration.namespace == name.namespace) if let Some(namespace) = &name.namespace {
// will always be in this vector let name_namespace_declaration = namespace_declarations_stack
.unwrap(); .iter()
let prefix = &namespace_declaration.prefix; .rfind(|namespace_declaration| namespace_declaration.namespace == *namespace)
.ok_or(Error::UndeclaredNamespace(namespace.clone()))?;
prefix = name_namespace_declaration.prefix.as_ref();
} else {
prefix = None
}
if let Some(prefix) = &prefix { if let Some(prefix) = &prefix {
e_tag = xml::ETag { e_tag = xml::ETag {
name: xml::QName::PrefixedName(xml::PrefixedName { name: xml::QName::PrefixedName(xml::PrefixedName {