#![warn(missing_docs)] #![warn(rust_2018_idioms)] //! A streaming XML validator that checks XML fragments against an XSD schema mod error; mod python; mod schema; mod token; use error::Error; use token::*; /// An XML validator that checks XML fragments against an XSD schema #[derive(Clone, Debug)] pub struct XmlSchemaValidator { current_tokens: Vec>, } /// The Result type used throughout this crate /// /// This is a type alias for `std::result::Result` with our custom `Error` type pub type Result = std::result::Result; impl XmlSchemaValidator { /// Create a new validator with the given schema text pub fn new(schema_text: &str) -> Result { let schema: schema::XsSchema = quick_xml::de::from_str(schema_text)?; let current_tokens = schema.xs_element.iter().map(|element| { Box::new(Token::StartOfFile(StartOfFile::new(Box::new(element.clone())))) }).collect(); Ok(Self { current_tokens, }) } /// Append a fragment of XML to the validator pub fn append(&mut self, fragment: &str) -> Result<()> { for c in fragment.chars() { self.append_char(c)?; } Ok(()) } /// Append a single character to the validator fn append_char(&mut self, c: char) -> Result<()> { println!("Appending char: {}", c); let mut new_tokens = vec![]; for token in self.current_tokens.clone() { new_tokens.append(&mut token.append(c)); } if new_tokens.is_empty() { return Err(Error::InvalidXml("No continuations".to_string())); } self.current_tokens = new_tokens; Ok(()) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_element_open() { let schema_text = std::fs::read_to_string("../../action_schema.xsd").unwrap(); let input = ""; let mut validator = XmlSchemaValidator::new(&schema_text).unwrap(); validator.append(input).unwrap(); } #[test] fn test_element_open_whitespace() { let schema_text = std::fs::read_to_string("../../action_schema.xsd").unwrap(); let input = ""; let mut validator = XmlSchemaValidator::new(&schema_text).unwrap(); validator.append(input).unwrap(); } #[test] fn test_element_open_invalid_name() { let schema_text = std::fs::read_to_string("../../action_schema.xsd").unwrap(); let input = "