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),
DuplicateAttribute(String),
UnqualifiedNamespace(String),
MismatchedEndTag(String, String),
MismatchedEndTag(Name, Name),
NotInElement(String),
ExtraData(String),
}

View File

@ -392,51 +392,49 @@ impl<R> Reader<R> {
fn end_tag_from_xml(
depth: &mut Vec<Name>,
namespaces: &mut Vec<HashSet<NamespaceDeclaration>>,
e_tag: xml::ETag,
namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
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<R> Reader<R> {
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();