xml-schema-derive 0.3.0

Structure generator from XSD source file
Documentation
use std::collections::BTreeMap;
use std::io::Cursor;
use xml::namespace::Namespace;
use xml::reader::{EventReader, XmlEvent};

#[derive(Clone, Debug)]
pub struct XsdContext {
  module_namespace_mappings: BTreeMap<String, String>,
  pub namespace: Namespace,
  xml_schema_prefix: Option<String>,
  is_in_sub_module: bool,
}

impl XsdContext {
  pub fn new(content: &str) -> Result<Self, String> {
    let cursor = Cursor::new(content);
    let parser = EventReader::new(cursor);

    for xml_element in parser {
      match xml_element {
        Ok(XmlEvent::StartElement {
          name, namespace, ..
        }) => {
          if name.namespace == Some("http://www.w3.org/2001/XMLSchema".to_string())
            && name.local_name == "schema"
          {
            let module_namespace_mappings = BTreeMap::new();
            let xml_schema_prefix = name.prefix;

            return Ok(XsdContext {
              module_namespace_mappings,
              namespace,
              xml_schema_prefix,
              is_in_sub_module: false,
            });
          }
        }
        Err(_) => break,
        _ => {}
      }
    }

    Err("Bad XML Schema, unable to found schema element.".to_string())
  }

  pub fn with_module_namespace_mappings(
    mut self,
    module_namespace_mappings: &BTreeMap<String, String>,
  ) -> Self {
    self.module_namespace_mappings = module_namespace_mappings.clone();
    self
  }

  pub fn has_xml_schema_prefix(&self) -> bool {
    self.xml_schema_prefix.is_some()
  }

  pub fn match_xml_schema_prefix(&self, value: &str) -> bool {
    self.xml_schema_prefix == Some(value.to_string())
  }

  pub fn get_module(&self, prefix: &str) -> Option<String> {
    self
      .namespace
      .get(prefix)
      .map(|namespace| {
        self
          .module_namespace_mappings
          .get(namespace)
          .map(|module| module.to_owned())
      })
      .unwrap_or_else(|| None)
  }

  pub fn set_is_in_sub_module(&mut self, is_in_sub_module: bool) {
    self.is_in_sub_module = is_in_sub_module;
  }

  pub fn is_in_sub_module(&self) -> bool {
    self.is_in_sub_module
  }
}

#[test]
fn get_module() {
  let context = XsdContext::new(
    r#"
    <xs:schema
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:example="http://example.com"
      >
    </xs:schema>
  "#,
  )
  .unwrap();

  let mut mapping = BTreeMap::new();
  mapping.insert(
    "http://example.com".to_string(),
    "crate::example".to_string(),
  );
  let context = context.with_module_namespace_mappings(&mapping);

  assert_eq!(
    context.get_module("example"),
    Some("crate::example".to_string())
  );
  assert_eq!(context.get_module("other"), None);
}

#[test]
fn bad_schema_definition() {
  let context = XsdContext::new(
    r#"
    <xs:schema
      xmlns="http://www.w3.org/2001/XMLSchema"
      >
    </xs:schema>
  "#,
  );

  assert!(context.is_err());
}