From caf8b7506e1fb1ccd8e3f43c897a02db90397dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?cel=20=F0=9F=8C=B8?= Date: Tue, 19 Nov 2024 16:26:59 +0000 Subject: [PATCH] implement end tag match check --- src/error.rs | 2 +- src/reader.rs | 94 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/error.rs b/src/error.rs index 2d96666..fcf43eb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -13,7 +13,7 @@ pub enum Error { DuplicateNameSpaceDeclaration(NamespaceDeclaration), DuplicateAttribute(String), UnqualifiedNamespace(String), - MismatchedEndTag(String, String), + MismatchedEndTag(Name, Name), NotInElement(String), ExtraData(String), } diff --git a/src/reader.rs b/src/reader.rs index a05e73b..abc3354 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -392,51 +392,49 @@ impl Reader { fn end_tag_from_xml( depth: &mut Vec, - namespaces: &mut Vec>, - e_tag: xml::ETag, + namespace_declarations: &mut Vec>, + xml_e_tag: xml::ETag, ) -> Result<()> { if let Some(s_tag_name) = depth.pop() { - let (namespace, name); - let namespace_declarations: Vec<_> = namespaces.iter().flatten().collect(); - match e_tag.name { - xml::QName::PrefixedName(ref prefixed_name) => { - namespace = namespace_declarations + let e_tag_namespace_declaration; + let e_tag_local_name = xml_e_tag.name.local_part().to_string(); + let namespace_declarations_stack: Vec<_> = + namespace_declarations.iter().flatten().collect(); + + match xml_e_tag.name.prefix() { + Some(prefix) => { + e_tag_namespace_declaration = namespace_declarations_stack .iter() - .rfind(|namespace| { - namespace.prefix.as_deref() == Some(**prefixed_name.prefix) - }) - .map(|namespace_decl| namespace_decl.namespace.clone()) - .ok_or_else(|| { - return Error::UnqualifiedNamespace((&e_tag.name).to_string()); - })?; - name = prefixed_name.local_part.to_string(); + .rfind(|namespace| namespace.prefix.as_deref() == Some(prefix)); } - xml::QName::UnprefixedName(ref unprefixed_name) => { - namespace = namespace_declarations + None => { + e_tag_namespace_declaration = namespace_declarations_stack .iter() - .rfind(|namespace| namespace.prefix.as_deref() == None) - .map(|namespace_decl| namespace_decl.namespace.clone()) - .ok_or_else(|| { - return Error::UnqualifiedNamespace(e_tag.name.to_string()); - })?; - name = unprefixed_name.to_string(); + .rfind(|namespace| namespace.prefix == None); } } + + let e_tag_namespace = e_tag_namespace_declaration + .ok_or_else(|| Error::UnqualifiedNamespace(xml_e_tag.name.to_string()))? + .namespace + .clone(); + let e_tag_name = Name { - namespace, - local_name: name, + namespace: e_tag_namespace, + local_name: e_tag_local_name, }; + + if e_tag_name != s_tag_name { + return Err(Error::MismatchedEndTag(s_tag_name, e_tag_name)); + } if s_tag_name == e_tag_name { - namespaces.pop(); + namespace_declarations.pop(); return Ok(()); } else { - return Err(Error::MismatchedEndTag( - s_tag_name.local_name, - e_tag.name.to_string(), - )); + return Err(Error::MismatchedEndTag(s_tag_name, e_tag_name)); } } else { - return Err(Error::NotInElement(e_tag.name.to_string())); + return Err(Error::NotInElement(xml_e_tag.name.to_string())); } } @@ -524,6 +522,40 @@ impl Reader { local_name: element_local_name, }; + // end tag name match check + + if let Some(xml_e_name) = xml_e_name { + let e_tag_namespace_declaration; + let e_tag_local_name = xml_e_name.local_part().to_string(); + + match xml_e_name.prefix() { + Some(prefix) => { + e_tag_namespace_declaration = namespace_declarations_stack + .iter() + .rfind(|namespace| namespace.prefix.as_deref() == Some(prefix)); + } + None => { + e_tag_namespace_declaration = namespace_declarations_stack + .iter() + .rfind(|namespace| namespace.prefix == None); + } + } + + let e_tag_namespace = e_tag_namespace_declaration + .ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))? + .namespace + .clone(); + + let e_tag_name = Name { + namespace: e_tag_namespace, + local_name: e_tag_local_name, + }; + + if e_tag_name != element_name { + return Err(Error::MismatchedEndTag(element_name, e_tag_name)); + } + } + // attributes let mut attributes = HashMap::new();