diff --git a/src/element.rs b/src/element.rs index d883c04..5b5f048 100644 --- a/src/element.rs +++ b/src/element.rs @@ -22,7 +22,7 @@ pub struct NamespaceDeclaration { // names are qualified, they contain a reference to the namespace (held within the reader/writer) #[derive(PartialEq, Eq, Hash, Clone, Debug)] pub struct Name { - pub namespace: String, + pub namespace: Option, pub local_name: String, } diff --git a/src/reader.rs b/src/reader.rs index abc3354..8387373 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -312,7 +312,7 @@ impl Reader { .chain(element_namespace_declarations.iter()) .collect(); - // element name and default attribute namespace + // element name let element_namespace_declaration; let element_local_name = s_tag.name.local_part().to_string(); @@ -330,10 +330,8 @@ impl Reader { } } - let element_default_namespace = element_namespace_declaration - .ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))? - .namespace - .clone(); + let element_default_namespace = + element_namespace_declaration.map(|decl| decl.namespace.clone()); let element_name = Name { namespace: element_default_namespace, @@ -361,20 +359,24 @@ impl Reader { 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 { - let name = Name { - namespace: namespace_declaration.namespace.clone(), + name = Name { + namespace: Some(namespace_declaration.namespace.clone()), 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 { - 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 Reader { } let e_tag_namespace = e_tag_namespace_declaration - .ok_or_else(|| Error::UnqualifiedNamespace(xml_e_tag.name.to_string()))? - .namespace + .map(|decl| decl.namespace.clone()) .clone(); let e_tag_name = Name { @@ -512,10 +513,8 @@ impl Reader { } } - let element_default_namespace = element_namespace_declaration - .ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))? - .namespace - .clone(); + let element_default_namespace = + element_namespace_declaration.map(|decl| decl.namespace.clone()); let element_name = Name { namespace: element_default_namespace, @@ -541,10 +540,7 @@ impl Reader { } } - let e_tag_namespace = e_tag_namespace_declaration - .ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))? - .namespace - .clone(); + let e_tag_namespace = e_tag_namespace_declaration.map(|decl| decl.namespace.clone()); let e_tag_name = Name { namespace: e_tag_namespace, @@ -577,20 +573,24 @@ impl Reader { 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 { - let name = Name { - namespace: namespace_declaration.namespace.clone(), + name = Name { + namespace: Some(namespace_declaration.namespace.clone()), 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 { - 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())); } } diff --git a/src/writer.rs b/src/writer.rs index 9e770c7..4881f57 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -23,19 +23,24 @@ impl Writer { } 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 .iter() .flatten() .chain(&element.namespace_declarations) .collect(); - let name_namespace_declaration = namespace_declarations_stack - .iter() - .rfind(|namespace_declaration| { - namespace_declaration.namespace == element.name.namespace - }) - .ok_or(Error::UndeclaredNamespace(element.name.namespace.clone()))?; - let prefix = &name_namespace_declaration.prefix; + + let prefix; + if let Some(namespace) = &element.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 name; if let Some(prefix) = &prefix { name = xml::QName::PrefixedName(xml::PrefixedName { @@ -48,8 +53,6 @@ impl Writer { )?) } - namespace_declarations_stack.push(name_namespace_declaration); - let mut attributes = Vec::new(); for namespace_declaration in &element.namespace_declarations { @@ -67,6 +70,39 @@ impl Writer { 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 }; s_tag.write(&mut self.inner).await?; @@ -82,12 +118,18 @@ impl Writer { let e_tag; let namespace_declarations_stack: Vec<_> = self.namespace_declarations.iter().flatten().collect(); - let namespace_declaration = namespace_declarations_stack - .iter() - .rfind(|namespace_declaration| namespace_declaration.namespace == name.namespace) - // will always be in this vector - .unwrap(); - let prefix = &namespace_declaration.prefix; + + 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 + } + if let Some(prefix) = &prefix { e_tag = xml::ETag { name: xml::QName::PrefixedName(xml::PrefixedName {