Skip to content

Commit

Permalink
Merge pull request #147 from lirkwood/main
Browse files Browse the repository at this point in the history
Added support for all element.
  • Loading branch information
DmitrySamoylov authored Mar 19, 2024
2 parents 7c31c6e + 008e0a3 commit 0834ded
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 0 deletions.
39 changes: 39 additions & 0 deletions xsd-parser/src/parser/all.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::cell::RefCell;

use roxmltree::Node;

use crate::parser::node_parser::parse_node;
use crate::parser::types::{RsEntity, Struct, StructField, TypeModifier};
use crate::parser::utils::{enum_to_field, get_documentation, get_parent_name};
use crate::parser::xsd_elements::{ElementType, XsdNode};

pub fn parse_all(node: &Node, parent: &Node) -> RsEntity {
let name = get_parent_name(node);
RsEntity::Struct(Struct {
name: name.into(),
comment: get_documentation(parent),
subtypes: vec![],
fields: RefCell::new(elements_to_fields(node, name)),
..Default::default()
})
}

fn elements_to_fields(choice: &Node, parent_name: &str) -> Vec<StructField> {
choice
.children()
.filter(|n| n.is_element() && n.xsd_type() != ElementType::Annotation)
.map(|n| match parse_node(&n, choice) {
RsEntity::StructField(mut sf) => {
if sf.type_name.ends_with(parent_name) {
sf.type_modifiers.push(TypeModifier::Recursive)
}
sf
}
RsEntity::Enum(mut en) => {
en.name = format!("{}Choice", parent_name);
enum_to_field(en)
}
_ => unreachable!("\nError: {:?}\n{:?}", n, parse_node(&n, choice)),
})
.collect()
}
1 change: 1 addition & 0 deletions xsd-parser/src/parser/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const SUPPORTED_CONTENT_TYPES: [ElementType; 2] =
pub fn parse_element(node: &Node, parent: &Node) -> RsEntity {
match parent.xsd_type() {
ElementType::Schema => parse_global_element(node),
ElementType::All => parse_field_of_sequence(node, parent),
ElementType::Sequence => parse_field_of_sequence(node, parent),
ElementType::Choice => parse_case_of_choice(node),
_ => element_default(node),
Expand Down
1 change: 1 addition & 0 deletions xsd-parser/src/parser/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod all;
mod any;
mod any_attribute;
mod attribute;
Expand Down
2 changes: 2 additions & 0 deletions xsd-parser/src/parser/node_parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use roxmltree::Node;

use crate::parser::all::parse_all;
use crate::parser::any::parse_any;
use crate::parser::any_attribute::parse_any_attribute;
use crate::parser::attribute::parse_attribute;
Expand All @@ -23,6 +24,7 @@ pub fn parse_node(node: &Node, parent: &Node) -> RsEntity {
use ElementType::*;

match node.xsd_type() {
All => parse_all(node, parent),
Any => parse_any(node),
AnyAttribute => parse_any_attribute(node),
Attribute => parse_attribute(node, parent),
Expand Down
8 changes: 8 additions & 0 deletions xsd-parser/tests/all/example.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<exam:Foo xmlns:exam="http://example.com">
<exam:TwiceOrMore>111</exam:TwiceOrMore>
<exam:Once>222</exam:Once>
<exam:TwiceOrMore>333</exam:TwiceOrMore>
<exam:OnceSpecify>444</exam:OnceSpecify>
<exam:TwiceOrMore>555</exam:TwiceOrMore>
</exam:Foo>
19 changes: 19 additions & 0 deletions xsd-parser/tests/all/expected.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
#[yaserde(prefix = "tns", namespace = "tns: http://example.com")]
pub struct FooType {
#[yaserde(prefix = "tns", rename = "Once")]
pub once: i32,

#[yaserde(prefix = "tns", rename = "Optional")]
pub optional: Option<i32>,

#[yaserde(prefix = "tns", rename = "OnceSpecify")]
pub once_specify: i32,

#[yaserde(prefix = "tns", rename = "TwiceOrMore")]
pub twice_or_more: Vec<i32>,
}

impl Validate for FooType {}

// pub type Foo = FooType;
16 changes: 16 additions & 0 deletions xsd-parser/tests/all/input.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.com"
targetNamespace="http://example.com"
elementFormDefault="qualified">
<xs:complexType name="FooType">
<xs:all>
<xs:element name="Once" type="xs:int"/>
<xs:element name="Optional" type="xs:int" minOccurs="0"/>
<xs:element name="OnceSpecify" type="xs:int" minOccurs="1"/>
<xs:element name="TwiceOrMore" type="xs:int" minOccurs="2" maxOccurs="unbounded"/>
</xs:all>
</xs:complexType>

<xs:element name="Foo" type="tns:FooType"/>
</xs:schema>
35 changes: 35 additions & 0 deletions xsd-parser/tests/all/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::utils;

#[test]
fn deserialization_works() {
mod expected {
use xsd_parser::generator::validator::Validate;
use yaserde_derive::{YaDeserialize, YaSerialize};

include!("expected.rs");
}

let ser = include_str!("example.xml");

let de: expected::FooType = yaserde::de::from_str(ser).unwrap();

assert_eq!(
de,
expected::FooType {
once: 222,
optional: None,
once_specify: 444,
twice_or_more: vec![111, 333, 555]
}
);
}

#[test]
fn generator_does_not_panic() {
println!("{}", utils::generate(include_str!("input.xsd")))
}

#[test]
fn generator_output_has_correct_ast() {
utils::ast_test(include_str!("input.xsd"), include_str!("expected.rs"));
}
1 change: 1 addition & 0 deletions xsd-parser/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[macro_use]
mod utils;
mod all;
mod any;
mod choice;
mod complex_type;
Expand Down

0 comments on commit 0834ded

Please sign in to comment.