Skip to content

Commit 0834ded

Browse files
Merge pull request #147 from lirkwood/main
Added support for all element.
2 parents 7c31c6e + 008e0a3 commit 0834ded

File tree

9 files changed

+122
-0
lines changed

9 files changed

+122
-0
lines changed

xsd-parser/src/parser/all.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use std::cell::RefCell;
2+
3+
use roxmltree::Node;
4+
5+
use crate::parser::node_parser::parse_node;
6+
use crate::parser::types::{RsEntity, Struct, StructField, TypeModifier};
7+
use crate::parser::utils::{enum_to_field, get_documentation, get_parent_name};
8+
use crate::parser::xsd_elements::{ElementType, XsdNode};
9+
10+
pub fn parse_all(node: &Node, parent: &Node) -> RsEntity {
11+
let name = get_parent_name(node);
12+
RsEntity::Struct(Struct {
13+
name: name.into(),
14+
comment: get_documentation(parent),
15+
subtypes: vec![],
16+
fields: RefCell::new(elements_to_fields(node, name)),
17+
..Default::default()
18+
})
19+
}
20+
21+
fn elements_to_fields(choice: &Node, parent_name: &str) -> Vec<StructField> {
22+
choice
23+
.children()
24+
.filter(|n| n.is_element() && n.xsd_type() != ElementType::Annotation)
25+
.map(|n| match parse_node(&n, choice) {
26+
RsEntity::StructField(mut sf) => {
27+
if sf.type_name.ends_with(parent_name) {
28+
sf.type_modifiers.push(TypeModifier::Recursive)
29+
}
30+
sf
31+
}
32+
RsEntity::Enum(mut en) => {
33+
en.name = format!("{}Choice", parent_name);
34+
enum_to_field(en)
35+
}
36+
_ => unreachable!("\nError: {:?}\n{:?}", n, parse_node(&n, choice)),
37+
})
38+
.collect()
39+
}

xsd-parser/src/parser/element.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const SUPPORTED_CONTENT_TYPES: [ElementType; 2] =
1414
pub fn parse_element(node: &Node, parent: &Node) -> RsEntity {
1515
match parent.xsd_type() {
1616
ElementType::Schema => parse_global_element(node),
17+
ElementType::All => parse_field_of_sequence(node, parent),
1718
ElementType::Sequence => parse_field_of_sequence(node, parent),
1819
ElementType::Choice => parse_case_of_choice(node),
1920
_ => element_default(node),

xsd-parser/src/parser/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod all;
12
mod any;
23
mod any_attribute;
34
mod attribute;

xsd-parser/src/parser/node_parser.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use roxmltree::Node;
22

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

2526
match node.xsd_type() {
27+
All => parse_all(node, parent),
2628
Any => parse_any(node),
2729
AnyAttribute => parse_any_attribute(node),
2830
Attribute => parse_attribute(node, parent),

xsd-parser/tests/all/example.xml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<exam:Foo xmlns:exam="http://example.com">
3+
<exam:TwiceOrMore>111</exam:TwiceOrMore>
4+
<exam:Once>222</exam:Once>
5+
<exam:TwiceOrMore>333</exam:TwiceOrMore>
6+
<exam:OnceSpecify>444</exam:OnceSpecify>
7+
<exam:TwiceOrMore>555</exam:TwiceOrMore>
8+
</exam:Foo>

xsd-parser/tests/all/expected.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
2+
#[yaserde(prefix = "tns", namespace = "tns: http://example.com")]
3+
pub struct FooType {
4+
#[yaserde(prefix = "tns", rename = "Once")]
5+
pub once: i32,
6+
7+
#[yaserde(prefix = "tns", rename = "Optional")]
8+
pub optional: Option<i32>,
9+
10+
#[yaserde(prefix = "tns", rename = "OnceSpecify")]
11+
pub once_specify: i32,
12+
13+
#[yaserde(prefix = "tns", rename = "TwiceOrMore")]
14+
pub twice_or_more: Vec<i32>,
15+
}
16+
17+
impl Validate for FooType {}
18+
19+
// pub type Foo = FooType;

xsd-parser/tests/all/input.xsd

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
3+
xmlns:tns="http://example.com"
4+
targetNamespace="http://example.com"
5+
elementFormDefault="qualified">
6+
<xs:complexType name="FooType">
7+
<xs:all>
8+
<xs:element name="Once" type="xs:int"/>
9+
<xs:element name="Optional" type="xs:int" minOccurs="0"/>
10+
<xs:element name="OnceSpecify" type="xs:int" minOccurs="1"/>
11+
<xs:element name="TwiceOrMore" type="xs:int" minOccurs="2" maxOccurs="unbounded"/>
12+
</xs:all>
13+
</xs:complexType>
14+
15+
<xs:element name="Foo" type="tns:FooType"/>
16+
</xs:schema>

xsd-parser/tests/all/mod.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use super::utils;
2+
3+
#[test]
4+
fn deserialization_works() {
5+
mod expected {
6+
use xsd_parser::generator::validator::Validate;
7+
use yaserde_derive::{YaDeserialize, YaSerialize};
8+
9+
include!("expected.rs");
10+
}
11+
12+
let ser = include_str!("example.xml");
13+
14+
let de: expected::FooType = yaserde::de::from_str(ser).unwrap();
15+
16+
assert_eq!(
17+
de,
18+
expected::FooType {
19+
once: 222,
20+
optional: None,
21+
once_specify: 444,
22+
twice_or_more: vec![111, 333, 555]
23+
}
24+
);
25+
}
26+
27+
#[test]
28+
fn generator_does_not_panic() {
29+
println!("{}", utils::generate(include_str!("input.xsd")))
30+
}
31+
32+
#[test]
33+
fn generator_output_has_correct_ast() {
34+
utils::ast_test(include_str!("input.xsd"), include_str!("expected.rs"));
35+
}

xsd-parser/tests/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#[macro_use]
22
mod utils;
3+
mod all;
34
mod any;
45
mod choice;
56
mod complex_type;

0 commit comments

Comments
 (0)