fix attribute namespace resolution
This commit is contained in:
		
							parent
							
								
									c8ed16a2d1
								
							
						
					
					
						commit
						c2a84072ac
					
				| 
						 | 
				
			
			@ -19,7 +19,7 @@ pub struct NamespaceDeclaration {
 | 
			
		|||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
 | 
			
		||||
pub struct Name {
 | 
			
		||||
    pub namespace: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub local_name: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ pub struct Element {
 | 
			
		|||
    // namespace: String,
 | 
			
		||||
    // hashmap of explicit namespace declarations on the element itself only
 | 
			
		||||
    // possibly not needed as can be calculated at write time depending on context and qualified namespace, and for reading, element validity and namespaces are kept track of by the reader.
 | 
			
		||||
    // pub namespace_decl: HashSet<Namespace>,
 | 
			
		||||
    pub namespace_declarations: HashSet<NamespaceDeclaration>,
 | 
			
		||||
    // attributes can be in a different namespace than the element. how to make sure they are valid?
 | 
			
		||||
    // maybe include the namespace instead of or with the prefix
 | 
			
		||||
    // you can calculate the prefix from the namespaced name and the current writer context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										468
									
								
								src/reader.rs
								
								
								
								
							
							
						
						
									
										468
									
								
								src/reader.rs
								
								
								
								
							| 
						 | 
				
			
			@ -277,10 +277,12 @@ where
 | 
			
		|||
impl<R> Reader<R> {
 | 
			
		||||
    fn start_tag_from_xml(
 | 
			
		||||
        depth: &mut Vec<Name>,
 | 
			
		||||
        namespaces: &mut Vec<HashSet<NamespaceDeclaration>>,
 | 
			
		||||
        namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
 | 
			
		||||
        s_tag: xml::STag,
 | 
			
		||||
    ) -> Result<Element> {
 | 
			
		||||
        let mut namespace_declarations = HashSet::new();
 | 
			
		||||
        // namespace declarations on element
 | 
			
		||||
 | 
			
		||||
        let mut element_namespace_declarations = HashSet::new();
 | 
			
		||||
        for (prefix, namespace) in s_tag.attributes.iter().filter_map(|attribute| {
 | 
			
		||||
            if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
 | 
			
		||||
                Some((ns_name, value))
 | 
			
		||||
| 
						 | 
				
			
			@ -298,20 +300,49 @@ impl<R> Reader<R> {
 | 
			
		|||
                prefix,
 | 
			
		||||
                namespace: namespace.process()?,
 | 
			
		||||
            };
 | 
			
		||||
            if !namespace_declarations.insert(namespace.clone()) {
 | 
			
		||||
            if !element_namespace_declarations.insert(namespace.clone()) {
 | 
			
		||||
                return Err(Error::DuplicateNameSpaceDeclaration(namespace));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // all namespaces available to the element (from both parent elements and element itself)
 | 
			
		||||
        let namespace_stack: Vec<&NamespaceDeclaration> = namespaces
 | 
			
		||||
        // all namespaces available in the element scope (from both parent elements and element itself)
 | 
			
		||||
        let namespace_declarations_stack: Vec<&NamespaceDeclaration> = namespace_declarations
 | 
			
		||||
            .iter()
 | 
			
		||||
            .flatten()
 | 
			
		||||
            .chain(namespace_declarations.iter())
 | 
			
		||||
            .chain(element_namespace_declarations.iter())
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        let mut attributes = HashMap::new();
 | 
			
		||||
        // element name and default attribute namespace
 | 
			
		||||
 | 
			
		||||
        let element_namespace_declaration;
 | 
			
		||||
        let element_local_name = s_tag.name.local_part().to_string();
 | 
			
		||||
 | 
			
		||||
        match s_tag.name.prefix() {
 | 
			
		||||
            Some(prefix) => {
 | 
			
		||||
                element_namespace_declaration = namespace_declarations_stack
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
 | 
			
		||||
            }
 | 
			
		||||
            None => {
 | 
			
		||||
                element_namespace_declaration = namespace_declarations_stack
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let element_default_namespace = element_namespace_declaration
 | 
			
		||||
            .ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))?
 | 
			
		||||
            .namespace
 | 
			
		||||
            .clone();
 | 
			
		||||
 | 
			
		||||
        let element_name = Name {
 | 
			
		||||
            namespace: element_default_namespace,
 | 
			
		||||
            local_name: element_local_name,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // attributes
 | 
			
		||||
 | 
			
		||||
        let mut attributes = HashMap::new();
 | 
			
		||||
        for (q_name, value) in s_tag.attributes.iter().filter_map(|attribute| {
 | 
			
		||||
            if let xml::Attribute::Attribute { name, value } = attribute {
 | 
			
		||||
                Some((name, value))
 | 
			
		||||
| 
						 | 
				
			
			@ -319,28 +350,26 @@ impl<R> Reader<R> {
 | 
			
		|||
                None
 | 
			
		||||
            }
 | 
			
		||||
        }) {
 | 
			
		||||
            let namespace;
 | 
			
		||||
            let attribute_name;
 | 
			
		||||
            match q_name {
 | 
			
		||||
                xml::QName::PrefixedName(prefixed_name) => {
 | 
			
		||||
                    namespace = namespace_stack.iter().rfind(|namespace| {
 | 
			
		||||
                        namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
 | 
			
		||||
                    });
 | 
			
		||||
                    attribute_name = prefixed_name.local_part.to_string();
 | 
			
		||||
                }
 | 
			
		||||
                xml::QName::UnprefixedName(unprefixed_name) => {
 | 
			
		||||
                    namespace = namespace_stack
 | 
			
		||||
                        .iter()
 | 
			
		||||
                        .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
                    attribute_name = unprefixed_name.to_string();
 | 
			
		||||
            let attribute_namespace_declaration;
 | 
			
		||||
            let attribute_local_name = q_name.local_part().to_string();
 | 
			
		||||
            match q_name.prefix() {
 | 
			
		||||
                Some(prefix) => {
 | 
			
		||||
                    attribute_namespace_declaration =
 | 
			
		||||
                        namespace_declarations_stack
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            .rfind(|namespace_declaration| {
 | 
			
		||||
                                namespace_declaration.prefix.as_deref() == Some(prefix)
 | 
			
		||||
                            });
 | 
			
		||||
                }
 | 
			
		||||
                None => attribute_namespace_declaration = element_namespace_declaration,
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(namespace_declaration) = namespace {
 | 
			
		||||
            if let Some(namespace_declaration) = attribute_namespace_declaration {
 | 
			
		||||
                let name = Name {
 | 
			
		||||
                    namespace: namespace_declaration.namespace.clone(),
 | 
			
		||||
                    name: attribute_name,
 | 
			
		||||
                    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()));
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -349,38 +378,13 @@ impl<R> Reader<R> {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let name;
 | 
			
		||||
        let namespace;
 | 
			
		||||
        match &s_tag.name {
 | 
			
		||||
            xml::QName::PrefixedName(prefixed_name) => {
 | 
			
		||||
                namespace = namespace_stack
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .rfind(|namespace| namespace.prefix.as_deref() == Some(**prefixed_name.prefix));
 | 
			
		||||
                name = prefixed_name.local_part.to_string();
 | 
			
		||||
            }
 | 
			
		||||
            xml::QName::UnprefixedName(unprefixed_name) => {
 | 
			
		||||
                namespace = namespace_stack
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
                name = unprefixed_name.to_string();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        depth.push(element_name.clone());
 | 
			
		||||
 | 
			
		||||
        let namespace_declaration = (*namespace
 | 
			
		||||
            .ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))?)
 | 
			
		||||
        .clone();
 | 
			
		||||
 | 
			
		||||
        let name = Name {
 | 
			
		||||
            namespace: namespace_declaration.namespace,
 | 
			
		||||
            name,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        depth.push(name.clone());
 | 
			
		||||
 | 
			
		||||
        namespaces.push(namespace_declarations.clone());
 | 
			
		||||
        namespace_declarations.push(element_namespace_declarations.clone());
 | 
			
		||||
 | 
			
		||||
        return Ok(Element {
 | 
			
		||||
            name,
 | 
			
		||||
            name: element_name,
 | 
			
		||||
            namespace_declarations: element_namespace_declarations,
 | 
			
		||||
            attributes,
 | 
			
		||||
            content: Vec::new(),
 | 
			
		||||
        });
 | 
			
		||||
| 
						 | 
				
			
			@ -418,13 +422,16 @@ impl<R> Reader<R> {
 | 
			
		|||
                    name = unprefixed_name.to_string();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            let e_tag_name = Name { namespace, name };
 | 
			
		||||
            let e_tag_name = Name {
 | 
			
		||||
                namespace,
 | 
			
		||||
                local_name: name,
 | 
			
		||||
            };
 | 
			
		||||
            if s_tag_name == e_tag_name {
 | 
			
		||||
                namespaces.pop();
 | 
			
		||||
                return Ok(());
 | 
			
		||||
            } else {
 | 
			
		||||
                return Err(Error::MismatchedEndTag(
 | 
			
		||||
                    s_tag_name.name,
 | 
			
		||||
                    s_tag_name.local_name,
 | 
			
		||||
                    e_tag.name.to_string(),
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -434,240 +441,153 @@ impl<R> Reader<R> {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fn element_from_xml(
 | 
			
		||||
        namespaces: &mut Vec<HashSet<NamespaceDeclaration>>,
 | 
			
		||||
        namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
 | 
			
		||||
        element: xml::Element,
 | 
			
		||||
    ) -> Result<Element> {
 | 
			
		||||
        let xml_name;
 | 
			
		||||
        let xml_attributes;
 | 
			
		||||
        let xml_content;
 | 
			
		||||
        let xml_e_name;
 | 
			
		||||
 | 
			
		||||
        match element {
 | 
			
		||||
            xml::Element::Empty(empty_elem_tag) => {
 | 
			
		||||
                let mut namespace_declarations = HashSet::new();
 | 
			
		||||
                for (prefix, namespace) in
 | 
			
		||||
                    empty_elem_tag.attributes.iter().filter_map(|attribute| {
 | 
			
		||||
                        if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
 | 
			
		||||
                            Some((ns_name, value))
 | 
			
		||||
                        } else {
 | 
			
		||||
                            None
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                {
 | 
			
		||||
                    let prefix = match prefix {
 | 
			
		||||
                        xml::NSAttName::PrefixedAttName(prefixed_att_name) => {
 | 
			
		||||
                            Some(prefixed_att_name.to_string())
 | 
			
		||||
                        }
 | 
			
		||||
                        xml::NSAttName::DefaultAttName => None,
 | 
			
		||||
                    };
 | 
			
		||||
                    let namespace = NamespaceDeclaration {
 | 
			
		||||
                        prefix,
 | 
			
		||||
                        namespace: namespace.process()?,
 | 
			
		||||
                    };
 | 
			
		||||
                    if !namespace_declarations.insert(namespace.clone()) {
 | 
			
		||||
                        return Err(Error::DuplicateNameSpaceDeclaration(namespace));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // all namespaces available to the element (from both parent elements and element itself)
 | 
			
		||||
                let namespace_stack: Vec<&NamespaceDeclaration> = namespaces
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .flatten()
 | 
			
		||||
                    .chain(namespace_declarations.iter())
 | 
			
		||||
                    .collect();
 | 
			
		||||
 | 
			
		||||
                let mut attributes = HashMap::new();
 | 
			
		||||
 | 
			
		||||
                for (q_name, value) in empty_elem_tag.attributes.iter().filter_map(|attribute| {
 | 
			
		||||
                    if let xml::Attribute::Attribute { name, value } = attribute {
 | 
			
		||||
                        Some((name, value))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        None
 | 
			
		||||
                    }
 | 
			
		||||
                }) {
 | 
			
		||||
                    let namespace;
 | 
			
		||||
                    let attribute_name;
 | 
			
		||||
                    match q_name {
 | 
			
		||||
                        xml::QName::PrefixedName(prefixed_name) => {
 | 
			
		||||
                            namespace = namespace_stack.iter().rfind(|namespace| {
 | 
			
		||||
                                namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
 | 
			
		||||
                            });
 | 
			
		||||
                            attribute_name = prefixed_name.local_part.to_string();
 | 
			
		||||
                        }
 | 
			
		||||
                        xml::QName::UnprefixedName(unprefixed_name) => {
 | 
			
		||||
                            namespace = namespace_stack
 | 
			
		||||
                                .iter()
 | 
			
		||||
                                .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
                            attribute_name = unprefixed_name.to_string();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if let Some(namespace) = namespace {
 | 
			
		||||
                        let namespace = (*namespace).clone();
 | 
			
		||||
                        let name = Name {
 | 
			
		||||
                            namespace: namespace.namespace,
 | 
			
		||||
                            name: attribute_name,
 | 
			
		||||
                        };
 | 
			
		||||
                        let value = value.process()?;
 | 
			
		||||
                        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()));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let name;
 | 
			
		||||
                let namespace;
 | 
			
		||||
                match &empty_elem_tag.name {
 | 
			
		||||
                    xml::QName::PrefixedName(prefixed_name) => {
 | 
			
		||||
                        namespace = namespace_stack.iter().rfind(|namespace| {
 | 
			
		||||
                            namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
 | 
			
		||||
                        });
 | 
			
		||||
                        name = prefixed_name.local_part.to_string();
 | 
			
		||||
                    }
 | 
			
		||||
                    xml::QName::UnprefixedName(unprefixed_name) => {
 | 
			
		||||
                        namespace = namespace_stack
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
                        name = unprefixed_name.to_string();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let namespace = (*namespace
 | 
			
		||||
                    .ok_or_else(|| Error::UnqualifiedNamespace(empty_elem_tag.name.to_string()))?)
 | 
			
		||||
                .clone();
 | 
			
		||||
 | 
			
		||||
                let name = Name {
 | 
			
		||||
                    namespace: namespace.namespace,
 | 
			
		||||
                    name,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                return Ok(Element {
 | 
			
		||||
                    name,
 | 
			
		||||
                    attributes,
 | 
			
		||||
                    content: Vec::new(),
 | 
			
		||||
                });
 | 
			
		||||
                xml_name = empty_elem_tag.name;
 | 
			
		||||
                xml_attributes = empty_elem_tag.attributes;
 | 
			
		||||
                xml_content = None;
 | 
			
		||||
                xml_e_name = None;
 | 
			
		||||
            }
 | 
			
		||||
            xml::Element::NotEmpty(s_tag, content, e_tag) => {
 | 
			
		||||
                if s_tag.name != e_tag.name {
 | 
			
		||||
                    return Err(Error::MismatchedEndTag(
 | 
			
		||||
                        s_tag.name.to_string(),
 | 
			
		||||
                        e_tag.name.to_string(),
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
                let mut namespace_declarations = HashSet::new();
 | 
			
		||||
                for (prefix, namespace) in s_tag.attributes.iter().filter_map(|attribute| {
 | 
			
		||||
                    if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
 | 
			
		||||
                        Some((ns_name, value))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        None
 | 
			
		||||
                    }
 | 
			
		||||
                }) {
 | 
			
		||||
                    let prefix = match prefix {
 | 
			
		||||
                        xml::NSAttName::PrefixedAttName(prefixed_att_name) => {
 | 
			
		||||
                            Some(prefixed_att_name.to_string())
 | 
			
		||||
                        }
 | 
			
		||||
                        xml::NSAttName::DefaultAttName => None,
 | 
			
		||||
                    };
 | 
			
		||||
                    let namespace = NamespaceDeclaration {
 | 
			
		||||
                        prefix,
 | 
			
		||||
                        namespace: namespace.process()?,
 | 
			
		||||
                    };
 | 
			
		||||
                    if !namespace_declarations.insert(namespace.clone()) {
 | 
			
		||||
                        return Err(Error::DuplicateNameSpaceDeclaration(namespace));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // all namespaces available to the element (from both parent elements and element itself)
 | 
			
		||||
                let namespace_stack: Vec<&NamespaceDeclaration> = namespaces
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .flatten()
 | 
			
		||||
                    .chain(namespace_declarations.iter())
 | 
			
		||||
                    .collect();
 | 
			
		||||
 | 
			
		||||
                let mut attributes = HashMap::new();
 | 
			
		||||
 | 
			
		||||
                for (q_name, value) in s_tag.attributes.iter().filter_map(|attribute| {
 | 
			
		||||
                    if let xml::Attribute::Attribute { name, value } = attribute {
 | 
			
		||||
                        Some((name, value))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        None
 | 
			
		||||
                    }
 | 
			
		||||
                }) {
 | 
			
		||||
                    let namespace;
 | 
			
		||||
                    let attribute_name;
 | 
			
		||||
                    match q_name {
 | 
			
		||||
                        xml::QName::PrefixedName(prefixed_name) => {
 | 
			
		||||
                            namespace = namespace_stack.iter().rfind(|namespace| {
 | 
			
		||||
                                namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
 | 
			
		||||
                            });
 | 
			
		||||
                            attribute_name = prefixed_name.local_part.to_string();
 | 
			
		||||
                        }
 | 
			
		||||
                        xml::QName::UnprefixedName(unprefixed_name) => {
 | 
			
		||||
                            namespace = namespace_stack
 | 
			
		||||
                                .iter()
 | 
			
		||||
                                .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
                            attribute_name = unprefixed_name.to_string();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if let Some(namespace) = namespace {
 | 
			
		||||
                        let namespace = (*namespace).clone();
 | 
			
		||||
                        let name = Name {
 | 
			
		||||
                            namespace: namespace.namespace,
 | 
			
		||||
                            name: attribute_name,
 | 
			
		||||
                        };
 | 
			
		||||
                        let value = value.process()?;
 | 
			
		||||
                        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()));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let name;
 | 
			
		||||
                let namespace;
 | 
			
		||||
                match &s_tag.name {
 | 
			
		||||
                    xml::QName::PrefixedName(prefixed_name) => {
 | 
			
		||||
                        namespace = namespace_stack.iter().rfind(|namespace| {
 | 
			
		||||
                            namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
 | 
			
		||||
                        });
 | 
			
		||||
                        name = prefixed_name.local_part.to_string();
 | 
			
		||||
                    }
 | 
			
		||||
                    xml::QName::UnprefixedName(unprefixed_name) => {
 | 
			
		||||
                        namespace = namespace_stack
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
                        name = unprefixed_name.to_string();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let namespace = (*namespace
 | 
			
		||||
                    .ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))?)
 | 
			
		||||
                .clone();
 | 
			
		||||
 | 
			
		||||
                let name = Name {
 | 
			
		||||
                    namespace: namespace.namespace,
 | 
			
		||||
                    name,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                namespaces.push(namespace_declarations.clone());
 | 
			
		||||
 | 
			
		||||
                let content = Self::content_from_xml(namespaces, content)?;
 | 
			
		||||
 | 
			
		||||
                namespaces.pop();
 | 
			
		||||
 | 
			
		||||
                return Ok(Element {
 | 
			
		||||
                    name,
 | 
			
		||||
                    attributes,
 | 
			
		||||
                    content,
 | 
			
		||||
                });
 | 
			
		||||
                xml_name = s_tag.name;
 | 
			
		||||
                xml_attributes = s_tag.attributes;
 | 
			
		||||
                xml_content = Some(content);
 | 
			
		||||
                xml_e_name = Some(e_tag.name);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // namespace declarations on element
 | 
			
		||||
 | 
			
		||||
        let mut element_namespace_declarations = HashSet::new();
 | 
			
		||||
        for (prefix, namespace) in xml_attributes.iter().filter_map(|attribute| {
 | 
			
		||||
            if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
 | 
			
		||||
                Some((ns_name, value))
 | 
			
		||||
            } else {
 | 
			
		||||
                None
 | 
			
		||||
            }
 | 
			
		||||
        }) {
 | 
			
		||||
            let prefix = match prefix {
 | 
			
		||||
                xml::NSAttName::PrefixedAttName(prefixed_att_name) => {
 | 
			
		||||
                    Some(prefixed_att_name.to_string())
 | 
			
		||||
                }
 | 
			
		||||
                xml::NSAttName::DefaultAttName => None,
 | 
			
		||||
            };
 | 
			
		||||
            let namespace = NamespaceDeclaration {
 | 
			
		||||
                prefix,
 | 
			
		||||
                namespace: namespace.process()?,
 | 
			
		||||
            };
 | 
			
		||||
            if !element_namespace_declarations.insert(namespace.clone()) {
 | 
			
		||||
                return Err(Error::DuplicateNameSpaceDeclaration(namespace));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // all namespaces available in the element scope (from both parent elements and element itself)
 | 
			
		||||
        let namespace_declarations_stack: Vec<&NamespaceDeclaration> = namespace_declarations
 | 
			
		||||
            .iter()
 | 
			
		||||
            .flatten()
 | 
			
		||||
            .chain(element_namespace_declarations.iter())
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        // element name and default attribute namespace
 | 
			
		||||
 | 
			
		||||
        let element_namespace_declaration;
 | 
			
		||||
        let element_local_name = xml_name.local_part().to_string();
 | 
			
		||||
 | 
			
		||||
        match xml_name.prefix() {
 | 
			
		||||
            Some(prefix) => {
 | 
			
		||||
                element_namespace_declaration = namespace_declarations_stack
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
 | 
			
		||||
            }
 | 
			
		||||
            None => {
 | 
			
		||||
                element_namespace_declaration = namespace_declarations_stack
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .rfind(|namespace| namespace.prefix == None);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let element_default_namespace = element_namespace_declaration
 | 
			
		||||
            .ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))?
 | 
			
		||||
            .namespace
 | 
			
		||||
            .clone();
 | 
			
		||||
 | 
			
		||||
        let element_name = Name {
 | 
			
		||||
            namespace: element_default_namespace,
 | 
			
		||||
            local_name: element_local_name,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // attributes
 | 
			
		||||
 | 
			
		||||
        let mut attributes = HashMap::new();
 | 
			
		||||
        for (q_name, value) in xml_attributes.iter().filter_map(|attribute| {
 | 
			
		||||
            if let xml::Attribute::Attribute { name, value } = attribute {
 | 
			
		||||
                Some((name, value))
 | 
			
		||||
            } else {
 | 
			
		||||
                None
 | 
			
		||||
            }
 | 
			
		||||
        }) {
 | 
			
		||||
            let attribute_namespace_declaration;
 | 
			
		||||
            let attribute_local_name = q_name.local_part().to_string();
 | 
			
		||||
            match q_name.prefix() {
 | 
			
		||||
                Some(prefix) => {
 | 
			
		||||
                    attribute_namespace_declaration =
 | 
			
		||||
                        namespace_declarations_stack
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            .rfind(|namespace_declaration| {
 | 
			
		||||
                                namespace_declaration.prefix.as_deref() == Some(prefix)
 | 
			
		||||
                            });
 | 
			
		||||
                }
 | 
			
		||||
                None => attribute_namespace_declaration = element_namespace_declaration,
 | 
			
		||||
            }
 | 
			
		||||
            if let Some(namespace_declaration) = attribute_namespace_declaration {
 | 
			
		||||
                let name = Name {
 | 
			
		||||
                    namespace: 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()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let content;
 | 
			
		||||
        if let Some(xml_content) = xml_content {
 | 
			
		||||
            namespace_declarations.push(element_namespace_declarations.clone());
 | 
			
		||||
 | 
			
		||||
            content = Self::content_from_xml(namespace_declarations, xml_content)?;
 | 
			
		||||
 | 
			
		||||
            namespace_declarations.pop();
 | 
			
		||||
        } else {
 | 
			
		||||
            content = Vec::new();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Ok(Element {
 | 
			
		||||
            name: element_name,
 | 
			
		||||
            namespace_declarations: element_namespace_declarations,
 | 
			
		||||
            attributes,
 | 
			
		||||
            content,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn content_from_xml(
 | 
			
		||||
        namespaces: &mut Vec<HashSet<NamespaceDeclaration>>,
 | 
			
		||||
        element: xml::Content,
 | 
			
		||||
        xml_content: xml::Content,
 | 
			
		||||
    ) -> Result<Vec<Content>> {
 | 
			
		||||
        let mut content = Vec::new();
 | 
			
		||||
        let mut text = element.char_data.map(|str| String::from(*str));
 | 
			
		||||
        for (content_item, char_data) in element.content {
 | 
			
		||||
        let mut text = xml_content.char_data.map(|str| String::from(*str));
 | 
			
		||||
        for (content_item, char_data) in xml_content.content {
 | 
			
		||||
            match content_item {
 | 
			
		||||
                xml::ContentItem::Element(element) => {
 | 
			
		||||
                    text.map(|text| content.push(Content::Text(text)));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue