implement end tag match check
This commit is contained in:
parent
c2a84072ac
commit
caf8b7506e
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue