1use roxmltree::{Document, Node};
5
6use crate::{
7 ext::{
8 children_of_type, children_with_name, first_child_of_type, first_child_of_type_req,
9 first_child_with_name, first_child_with_name_opt, value_from_attr, value_from_attr_opt,
10 },
11 FromValue, XmlError, XmlLoad,
12};
13
14pub fn load_xsd_schema(document: &str) -> Result<XmlSchema, XmlError> {
16 let document = Document::parse(document).map_err(|e| XmlError {
17 span: 0..1,
18 error: crate::error::XmlErrorInner::Xml(e),
19 })?;
20 let root = document.root();
21 first_child_with_name(&root, "schema")
22}
23
24#[derive(Debug, Clone)]
25pub struct FacetValue {
27 pub value: String,
29 pub fixed: bool,
31}
32
33impl<'input> XmlLoad<'input> for FacetValue {
34 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
35 Ok(Self {
36 value: value_from_attr(node, "value")?,
37 fixed: value_from_attr_opt(node, "fixed")?.unwrap_or(false),
38 })
39 }
40}
41
42#[derive(Debug, Clone)]
43pub enum Facet {
45 MinExclusive(FacetValue),
47 MinInclusive(FacetValue),
49 MaxExclusive(FacetValue),
51 MaxInclusive(FacetValue),
53 TotalDigits(FacetValue),
55 FractionDigits(FacetValue),
57 Length(FacetValue),
59 MinLength(FacetValue),
61 MaxLength(FacetValue),
63 Enumeration(FacetValue),
65 WhiteSpace(FacetValue),
67 Pattern(FacetValue),
69}
70
71impl<'input> XmlLoad<'input> for Option<Facet> {
72 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
73 Ok(Some(match node.tag_name().name() {
74 "minExclusive" => Facet::MinExclusive(FacetValue::load(node)?),
75 "minInclusive" => Facet::MinInclusive(FacetValue::load(node)?),
76 "maxExclusive" => Facet::MaxExclusive(FacetValue::load(node)?),
77 "maxInclusive" => Facet::MaxInclusive(FacetValue::load(node)?),
78 "totalDigits" => Facet::TotalDigits(FacetValue::load(node)?),
79 "fractionDigits" => Facet::FractionDigits(FacetValue::load(node)?),
80 "length" => Facet::Length(FacetValue::load(node)?),
81 "minLength" => Facet::MinLength(FacetValue::load(node)?),
82 "maxLength" => Facet::MaxLength(FacetValue::load(node)?),
83 "enumeration" => Facet::Enumeration(FacetValue::load(node)?),
84 "whiteSpace" => Facet::WhiteSpace(FacetValue::load(node)?),
85 "pattern" => Facet::Pattern(FacetValue::load(node)?),
86 _ => return Ok(None),
87 }))
88 }
89}
90
91#[derive(Debug, Clone)]
92pub struct Restriction {
94 pub base: Option<String>,
96 pub facets: Vec<Facet>,
98 pub content: Option<SimpleType>,
100 pub particle: Option<TypeDefParticle>,
102 pub attributes: Vec<Attribute>,
104}
105
106impl<'input> XmlLoad<'input> for Restriction {
107 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
108 Ok(Self {
109 base: value_from_attr_opt(node, "base")?,
110 facets: children_of_type(node)?,
111 particle: first_child_of_type(node)?,
112 attributes: children_with_name(node, "")?,
113 content: first_child_with_name_opt(node, "simpleType")?,
114 })
115 }
116}
117
118#[derive(Debug, Clone)]
119pub struct List {
121 pub content: Option<SimpleType>,
123 pub item_type: Option<String>,
125}
126
127impl<'input> XmlLoad<'input> for List {
128 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
129 Ok(Self {
130 content: first_child_with_name_opt(node, "simpleType")?,
131 item_type: value_from_attr_opt(node, "itemType")?,
132 })
133 }
134}
135
136#[derive(Debug, Clone)]
137pub struct Union {
139 pub variants: Vec<SimpleType>,
141 pub member_types: Option<Vec<String>>,
143}
144
145impl<'input> XmlLoad<'input> for Union {
146 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
147 Ok(Self {
148 variants: children_with_name(node, "simpleType")?,
149 member_types: value_from_attr_opt(node, "memberTypes")?,
150 })
151 }
152}
153
154#[derive(Debug, Clone)]
155pub enum SimpleDerivation {
157 Restriction(Box<Restriction>),
159 List(Box<List>),
161 Union(Box<Union>),
163}
164
165impl<'input> XmlLoad<'input> for Option<SimpleDerivation> {
166 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
167 Ok(Some(match node.tag_name().name() {
168 "restriction" => SimpleDerivation::Restriction(Box::new(XmlLoad::load(node)?)),
169 "list" => SimpleDerivation::List(Box::new(XmlLoad::load(node)?)),
170 "union" => SimpleDerivation::Union(Box::new(XmlLoad::load(node)?)),
171 _ => return Ok(None),
172 }))
173 }
174}
175
176#[derive(Debug, Clone)]
177pub struct SimpleType {
179 pub name: Option<String>,
181 pub content: Option<SimpleDerivation>,
183}
184
185impl<'input> XmlLoad<'input> for SimpleType {
186 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
187 Ok(Self {
188 name: value_from_attr_opt(node, "name")?,
189 content: first_child_of_type(node)?,
190 })
191 }
192}
193
194#[derive(Debug, Clone)]
195pub struct Any {
197 pub min_occurs: Option<u32>,
199 pub max_uccors: Option<MaxOccurs>,
201}
202
203impl<'input> XmlLoad<'input> for Any {
204 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
205 Ok(Self {
206 min_occurs: value_from_attr_opt(node, "minOccurs")?,
207 max_uccors: value_from_attr_opt(node, "maxOccurs")?,
208 })
209 }
210}
211
212#[derive(Debug, Clone)]
214pub enum Particle {
215 Element(Element),
217 All(Group),
219 Choice(Group),
221 Sequence(Group),
223 Any(Any),
225}
226
227impl<'input> XmlLoad<'input> for Option<Particle> {
228 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
229 Ok(Some(match node.tag_name().name() {
230 "element" => Particle::Element(XmlLoad::load(node)?),
231 "all" => Particle::All(XmlLoad::load(node)?),
232 "choice" => Particle::Choice(XmlLoad::load(node)?),
233 "sequence" => Particle::Sequence(XmlLoad::load(node)?),
234 "any" => Particle::Any(XmlLoad::load(node)?),
235 _ => return Ok(None),
236 }))
237 }
238}
239
240#[derive(Debug, Clone)]
241pub enum NestedParticle {
243 Element(Element),
245 Choice(Group),
247 Sequence(Group),
249 Any(Any),
251}
252
253impl<'input> XmlLoad<'input> for Option<NestedParticle> {
254 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
255 Ok(Some(match node.tag_name().name() {
256 "element" => NestedParticle::Element(XmlLoad::load(node)?),
257 "choice" => NestedParticle::Choice(XmlLoad::load(node)?),
258 "sequence" => NestedParticle::Sequence(XmlLoad::load(node)?),
259 "any" => NestedParticle::Any(XmlLoad::load(node)?),
260 _ => return Ok(None),
261 }))
262 }
263}
264
265#[derive(Debug, Clone)]
266pub struct Group {
268 pub content: Vec<NestedParticle>,
270 pub min_occurs: Option<u32>,
272 pub max_uccors: Option<MaxOccurs>,
274}
275
276impl<'input> XmlLoad<'input> for Group {
277 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
278 Ok(Self {
279 content: children_of_type(node)?,
280 min_occurs: value_from_attr_opt(node, "minOccurs")?,
281 max_uccors: value_from_attr_opt(node, "maxOccurs")?,
282 })
283 }
284}
285
286#[derive(Debug, Clone)]
287pub enum TypeDefParticle {
289 All(Group),
291 Choice(Group),
293 Sequence(Group),
295}
296
297impl<'input> XmlLoad<'input> for Option<TypeDefParticle> {
298 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
299 Ok(Some(match node.tag_name().name() {
300 "all" => TypeDefParticle::All(XmlLoad::load(node)?),
301 "choice" => TypeDefParticle::Choice(XmlLoad::load(node)?),
302 "sequence" => TypeDefParticle::Sequence(XmlLoad::load(node)?),
303 _ => return Ok(None),
304 }))
305 }
306}
307
308#[derive(Debug, Clone)]
309pub struct Extension {
311 pub content: Option<TypeDefParticle>,
313 pub attributes: Vec<Attribute>,
315 pub base: String,
317}
318
319impl<'input> XmlLoad<'input> for Extension {
320 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
321 Ok(Self {
322 content: first_child_of_type(node)?,
323 attributes: children_with_name(node, "attributes")?,
324 base: value_from_attr(node, "base")?,
325 })
326 }
327}
328
329#[derive(Debug, Clone)]
330pub enum SimpleContent {
332 Restriction(Restriction),
334 Extension(Extension),
336}
337
338impl<'input> XmlLoad<'input> for Option<SimpleContent> {
339 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
340 Ok(Some(match node.tag_name().name() {
341 "restriction" => SimpleContent::Restriction(XmlLoad::load(node)?),
342 "extension" => SimpleContent::Extension(XmlLoad::load(node)?),
343 _ => return Ok(None),
344 }))
345 }
346}
347
348#[derive(Debug, Clone)]
349pub struct ComplexRestriction {
351 pub base: Restriction,
353 pub particle: Option<TypeDefParticle>,
355}
356
357impl<'input> XmlLoad<'input> for ComplexRestriction {
358 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
359 Ok(Self {
360 base: Restriction::load(node)?,
361 particle: first_child_of_type(node)?,
362 })
363 }
364}
365
366#[derive(Debug, Clone)]
367pub enum ComplexContent {
369 Restriction(ComplexRestriction),
371 Extension(Extension),
373}
374
375impl<'input> XmlLoad<'input> for Option<ComplexContent> {
376 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
377 Ok(Some(match node.tag_name().name() {
378 "restriction" => ComplexContent::Restriction(XmlLoad::load(node)?),
379 "extension" => ComplexContent::Extension(XmlLoad::load(node)?),
380 _ => return Ok(None),
381 }))
382 }
383}
384
385#[derive(Debug, Clone)]
386pub enum ComplexTypeContents {
388 Simple(SimpleContent),
390 Complex(ComplexContent),
392}
393
394impl<'input> XmlLoad<'input> for Option<ComplexTypeContents> {
395 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
396 Ok(Some(match node.tag_name().name() {
397 "simpleContent" => ComplexTypeContents::Simple(first_child_of_type_req(
398 node,
399 "restriction or extension",
400 )?),
401 "complexContent" => ComplexTypeContents::Complex(first_child_of_type_req(
402 node,
403 "restriction or extension",
404 )?),
405 _ => {
406 return Ok(None);
407 }
408 }))
409 }
410}
411
412#[derive(Debug, Clone)]
413pub struct ComplexType {
415 pub content: Option<ComplexTypeContents>,
417 pub particle: Option<TypeDefParticle>,
419 pub attributes: Vec<Attribute>,
421 pub name: Option<String>,
423}
424
425impl<'input> XmlLoad<'input> for ComplexType {
426 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
427 Ok(Self {
428 content: first_child_of_type(node)?,
429 particle: first_child_of_type(node)?,
430 attributes: children_with_name(node, "attribute")?,
431 name: value_from_attr_opt(node, "name")?,
432 })
433 }
434}
435
436#[derive(Debug, Clone)]
437pub enum ElementContents {
439 SimpleType(Box<SimpleType>),
441 ComplexType(Box<ComplexType>),
443}
444
445impl<'input> XmlLoad<'input> for Option<ElementContents> {
446 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
447 Ok(Some(match node.tag_name().name() {
448 "simpleType" => ElementContents::SimpleType(Box::new(XmlLoad::load(node)?)),
449 "complexType" => ElementContents::ComplexType(Box::new(XmlLoad::load(node)?)),
450 _ => return Ok(None),
451 }))
452 }
453}
454
455#[derive(Debug, Clone)]
456pub enum MaxOccurs {
458 Count(u32),
460 Unbounded,
462}
463
464impl FromValue for MaxOccurs {
465 fn from_value(node: &Node<'_, '_>, attr: &str, v: &str) -> Result<Self, XmlError> {
466 if v == "unbounded" {
467 return Ok(Self::Unbounded);
468 }
469
470 Ok(Self::Count(u32::from_value(node, attr, v)?))
471 }
472}
473
474#[derive(Debug, Clone)]
475pub enum AttributeUse {
477 Prohibited,
479 Optional,
481 Required,
483}
484
485impl FromValue for AttributeUse {
486 fn from_value(node: &Node<'_, '_>, attr: &str, v: &str) -> Result<Self, XmlError> {
487 match v {
488 "prohibited" => Ok(Self::Prohibited),
489 "optional" => Ok(Self::Optional),
490 "required" => Ok(Self::Required),
491 r => Err(XmlError::other(
492 node,
493 &format!("Unexpected value for {attr}: {r}"),
494 )),
495 }
496 }
497}
498
499#[derive(Debug, Clone)]
500pub struct Attribute {
502 pub content: Option<SimpleType>,
504 pub name: Option<String>,
506 pub r#ref: Option<String>,
508 pub r#type: Option<String>,
510 pub r#use: AttributeUse,
512 pub default: Option<String>,
514}
515
516impl<'input> XmlLoad<'input> for Attribute {
517 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
518 Ok(Self {
519 content: first_child_with_name_opt(node, "simpleType")?,
520 name: value_from_attr_opt(node, "name")?,
521 r#ref: value_from_attr_opt(node, "ref")?,
522 r#type: value_from_attr_opt(node, "type")?,
523 r#use: value_from_attr_opt(node, "use")?.unwrap_or(AttributeUse::Optional),
524 default: value_from_attr_opt(node, "default")?,
525 })
526 }
527}
528
529#[derive(Debug, Clone)]
530pub struct AttrDecls {
532 pub attributes: Vec<Attribute>,
534}
535
536impl<'input> XmlLoad<'input> for AttrDecls {
537 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
538 Ok(Self {
539 attributes: children_with_name(node, "attribute")?,
540 })
541 }
542}
543
544#[derive(Debug, Clone)]
545pub struct Element {
547 pub r#type: Option<String>,
549 pub default: Option<String>,
551 pub nillable: bool,
553 pub contents: Option<ElementContents>,
555 pub name: Option<String>,
557 pub r#ref: Option<String>,
559 pub min_occurs: Option<u32>,
561 pub max_occurs: Option<MaxOccurs>,
563}
564
565impl<'input> XmlLoad<'input> for Element {
566 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
567 Ok(Self {
568 r#type: value_from_attr_opt(node, "type")?,
569 default: value_from_attr_opt(node, "default")?,
570 nillable: value_from_attr_opt(node, "nillable")?.unwrap_or(false),
571 name: value_from_attr_opt(node, "name")?,
572 r#ref: value_from_attr_opt(node, "ref")?,
573 min_occurs: value_from_attr_opt(node, "minOccurs")?,
574 max_occurs: value_from_attr_opt(node, "maxOccurs")?,
575 contents: first_child_of_type(node)?,
576 })
577 }
578}
579
580#[derive(Debug)]
581pub enum XsdFileItem {
583 SimpleType(SimpleType),
585 ComplexType(ComplexType),
587 Element(Element),
589}
590
591impl<'input> XmlLoad<'input> for Option<XsdFileItem> {
592 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
593 Ok(Some(match node.tag_name().name() {
594 "simpleType" => XsdFileItem::SimpleType(XmlLoad::load(node)?),
595 "complexType" => XsdFileItem::ComplexType(XmlLoad::load(node)?),
596 "element" => XsdFileItem::Element(XmlLoad::load(node)?),
597 _ => return Ok(None),
598 }))
599 }
600}
601
602#[derive(Debug)]
603pub struct XmlSchema {
605 pub items: Vec<XsdFileItem>,
607 pub target_namespace: Option<String>,
609 pub version: Option<String>,
611}
612
613impl<'input> XmlLoad<'input> for XmlSchema {
614 fn load(node: &Node<'_, 'input>) -> Result<Self, XmlError> {
615 Ok(Self {
616 items: children_of_type(node)?,
617 target_namespace: value_from_attr_opt(node, "targetNamespace")?,
618 version: value_from_attr_opt(node, "version")?,
619 })
620 }
621}
622
623#[derive(Debug)]
624pub enum XsdFileType {
626 Simple(Box<SimpleType>),
628 Complex(Box<ComplexType>),
630}