// elements resemble a final tree, including inherited namespace information use std::collections::{HashMap, HashSet}; use crate::{ error::Error, xml::{self, Attribute}, }; // when are namespaces names chosen then if they are automatically calculated // namespaces are held by readers and writers. #[derive(PartialEq, Eq, Hash, Clone, Debug)] pub struct NamespaceDeclaration { pub prefix: Option, pub namespace: String, } // names are qualified, they contain a reference to the namespace (held within the reader/writer) #[derive(PartialEq, Eq, Hash, Clone, Debug)] pub struct Name { pub namespace: String, pub name: String, } #[derive(Debug)] pub enum Content { Element(Element), Text(String), PI, Comment(String), } // should this be a trait? #[derive(Debug)] pub struct Element { pub name: Name, // namespace: Name, // each element once created contains the qualified namespace information for that element // the name contains the qualified namespace so this is unnecessary // 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, // 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 // you can validate the prefix and calculate the namespace from the current reader context // this results in readers and writers being able to return qualification errors as they aren't able to create elements until every part is qualified. pub attributes: HashMap, pub content: Vec, } // impl<'s> TryFrom> for Element<'s> { // type Error = Error; // fn try_from(xml_element: xml::Element) -> Result { // match &xml_element { // xml::Element::Empty(empty_elem_tag) => { // let namespace_decl; // let attributes; // empty_elem_tag // .attributes // .into_iter() // .filter(|attribute| matches!(attribute, Attribute::NamespaceDeclaration(_))); // todo!() // } // xml::Element::NotEmpty(stag, content, etag) => todo!(), // } // } // } // example of deriving an element: // #[derive(XMLWrite, XMLRead)] // #[peanuts(xmlns = "jabber:client", xmlns:stream = "http://etherx.jabber.org/streams", prefix = "stream")] // pub struct Stream { // from: JID, // id: String, // to: JID, // version: String, // #[peanuts(namespace = "http://www.w3.org/XML/1998/namespace")] // lang: Lang, // } // note: if an element name has a prefix all unprefixed attributes are qualified by the namespace of the prefix, so in this example from's Name's namespace would be "http://etherx.jabber.org/streams"