implement end tag match check

This commit is contained in:
cel 🌸 2024-11-19 16:26:59 +00:00
parent c2a84072ac
commit caf8b7506e
2 changed files with 64 additions and 32 deletions

View File

@ -13,7 +13,7 @@ pub enum Error {
DuplicateNameSpaceDeclaration(NamespaceDeclaration), DuplicateNameSpaceDeclaration(NamespaceDeclaration),
DuplicateAttribute(String), DuplicateAttribute(String),
UnqualifiedNamespace(String), UnqualifiedNamespace(String),
MismatchedEndTag(String, String), MismatchedEndTag(Name, Name),
NotInElement(String), NotInElement(String),
ExtraData(String), ExtraData(String),
} }

View File

@ -392,51 +392,49 @@ impl<R> Reader<R> {
fn end_tag_from_xml( fn end_tag_from_xml(
depth: &mut Vec<Name>, depth: &mut Vec<Name>,
namespaces: &mut Vec<HashSet<NamespaceDeclaration>>, namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
e_tag: xml::ETag, xml_e_tag: xml::ETag,
) -> Result<()> { ) -> Result<()> {
if let Some(s_tag_name) = depth.pop() { if let Some(s_tag_name) = depth.pop() {
let (namespace, name); let e_tag_namespace_declaration;
let namespace_declarations: Vec<_> = namespaces.iter().flatten().collect(); let e_tag_local_name = xml_e_tag.name.local_part().to_string();
match e_tag.name { let namespace_declarations_stack: Vec<_> =
xml::QName::PrefixedName(ref prefixed_name) => { namespace_declarations.iter().flatten().collect();
namespace = namespace_declarations
match xml_e_tag.name.prefix() {
Some(prefix) => {
e_tag_namespace_declaration = namespace_declarations_stack
.iter() .iter()
.rfind(|namespace| { .rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
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();
} }
xml::QName::UnprefixedName(ref unprefixed_name) => { None => {
namespace = namespace_declarations e_tag_namespace_declaration = namespace_declarations_stack
.iter() .iter()
.rfind(|namespace| namespace.prefix.as_deref() == None) .rfind(|namespace| namespace.prefix == None);
.map(|namespace_decl| namespace_decl.namespace.clone())
.ok_or_else(|| {
return Error::UnqualifiedNamespace(e_tag.name.to_string());
})?;
name = unprefixed_name.to_string();
} }
} }
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 { let e_tag_name = Name {
namespace, namespace: e_tag_namespace,
local_name: name, 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 { if s_tag_name == e_tag_name {
namespaces.pop(); namespace_declarations.pop();
return Ok(()); return Ok(());
} else { } else {
return Err(Error::MismatchedEndTag( return Err(Error::MismatchedEndTag(s_tag_name, e_tag_name));
s_tag_name.local_name,
e_tag.name.to_string(),
));
} }
} else { } 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<R> Reader<R> {
local_name: element_local_name, 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 // attributes
let mut attributes = HashMap::new(); let mut attributes = HashMap::new();