polyxml 0.30.7__tar.gz → 0.31.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polyxml-0.30.7 → polyxml-0.31.0}/Cargo.lock +6 -6
- {polyxml-0.30.7 → polyxml-0.31.0}/Cargo.toml +1 -1
- {polyxml-0.30.7 → polyxml-0.31.0}/PKG-INFO +1 -1
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/ir/mod.rs +318 -1
- {polyxml-0.30.7 → polyxml-0.31.0}/pyproject.toml +1 -1
- {polyxml-0.30.7 → polyxml-0.31.0}/README.md +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/Cargo.toml +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/README.md +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/benches/support/tag_dispatch_fixtures.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/benches/tag_dispatch.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/cpp/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/csharp/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/go/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/java/codec.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/java/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/java/models.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/python/aot.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/python/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/rust/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/codegen/typescript/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/converters.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/error.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/json.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/lib.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/parser.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/schema.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/schema_parser/mod.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/serializer.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/transcoder.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/src/value.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/fixtures/lexical_union.xsd +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/fixtures/mixed_content.xsd +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/fixtures/ts_mixed_content_inheritance.xsd +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_adversarial_identifiers.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_conformance.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_core.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_csharp_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_json.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_lexical_union_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_mixed_content.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_pattern_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_python_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_rust_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_schema_audit.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_security.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_unbounded_choice.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/tests/test_xsi_type.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/Cargo.toml +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/README.md +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/benches/aot_vs_dataclass.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/src/lib.rs +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/tests/test_conformance.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/tests/test_generated_models.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/tests/test_json.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/tests/test_mixed_content.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/tests/test_polyxml.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-python/tests/test_xsi_type.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/python/polyxml/AGENT_GUIDE.md +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/python/polyxml/__init__.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/python/polyxml/compat/__init__.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/python/polyxml/compat/xsdata.py +0 -0
- {polyxml-0.30.7 → polyxml-0.31.0}/python/polyxml/py.typed +0 -0
|
@@ -608,7 +608,7 @@ dependencies = [
|
|
|
608
608
|
|
|
609
609
|
[[package]]
|
|
610
610
|
name = "polyxml"
|
|
611
|
-
version = "0.
|
|
611
|
+
version = "0.31.0"
|
|
612
612
|
dependencies = [
|
|
613
613
|
"criterion",
|
|
614
614
|
"heck",
|
|
@@ -629,14 +629,14 @@ dependencies = [
|
|
|
629
629
|
|
|
630
630
|
[[package]]
|
|
631
631
|
name = "polyxml-c"
|
|
632
|
-
version = "0.
|
|
632
|
+
version = "0.31.0"
|
|
633
633
|
dependencies = [
|
|
634
634
|
"polyxml",
|
|
635
635
|
]
|
|
636
636
|
|
|
637
637
|
[[package]]
|
|
638
638
|
name = "polyxml-cli"
|
|
639
|
-
version = "0.
|
|
639
|
+
version = "0.31.0"
|
|
640
640
|
dependencies = [
|
|
641
641
|
"clap",
|
|
642
642
|
"glob",
|
|
@@ -650,7 +650,7 @@ dependencies = [
|
|
|
650
650
|
|
|
651
651
|
[[package]]
|
|
652
652
|
name = "polyxml-js"
|
|
653
|
-
version = "0.
|
|
653
|
+
version = "0.31.0"
|
|
654
654
|
dependencies = [
|
|
655
655
|
"napi",
|
|
656
656
|
"napi-build",
|
|
@@ -660,7 +660,7 @@ dependencies = [
|
|
|
660
660
|
|
|
661
661
|
[[package]]
|
|
662
662
|
name = "polyxml-python"
|
|
663
|
-
version = "0.
|
|
663
|
+
version = "0.31.0"
|
|
664
664
|
dependencies = [
|
|
665
665
|
"lexical-core",
|
|
666
666
|
"polyxml",
|
|
@@ -670,7 +670,7 @@ dependencies = [
|
|
|
670
670
|
|
|
671
671
|
[[package]]
|
|
672
672
|
name = "polyxml-wasm"
|
|
673
|
-
version = "0.
|
|
673
|
+
version = "0.31.0"
|
|
674
674
|
dependencies = [
|
|
675
675
|
"polyxml",
|
|
676
676
|
"quick-xml",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
pub mod tarjan;
|
|
2
2
|
|
|
3
3
|
use serde::{Deserialize, Serialize};
|
|
4
|
-
use std::collections::{BTreeMap, HashMap};
|
|
4
|
+
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
|
5
5
|
use std::fmt;
|
|
6
6
|
|
|
7
7
|
/// Fully qualified XML Name (Namespace URI + Local Name).
|
|
@@ -467,6 +467,161 @@ pub struct SchemaIR {
|
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
impl SchemaIR {
|
|
470
|
+
/// Keep the selected global elements and all types that can occur beneath them.
|
|
471
|
+
/// The schema is parsed in full before this operation, so references can be
|
|
472
|
+
/// followed across imports and includes.
|
|
473
|
+
pub fn select_root_elements(&self, roots: &[String]) -> Result<Self, String> {
|
|
474
|
+
if roots.is_empty() {
|
|
475
|
+
return Ok(self.clone());
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
let mut selected_elements = BTreeSet::new();
|
|
479
|
+
for name in roots {
|
|
480
|
+
let matches: Vec<_> = if let Some(qualified) = name.strip_prefix('{') {
|
|
481
|
+
let (namespace, local) = qualified.split_once('}').ok_or_else(|| {
|
|
482
|
+
format!("Invalid root element '{name}': expected {{namespace}}local-name")
|
|
483
|
+
})?;
|
|
484
|
+
if local.is_empty() {
|
|
485
|
+
return Err(format!("Invalid root element '{name}': missing local name"));
|
|
486
|
+
}
|
|
487
|
+
self.elements
|
|
488
|
+
.keys()
|
|
489
|
+
.filter(|q| {
|
|
490
|
+
q.namespace.as_deref().unwrap_or("") == namespace && q.local == local
|
|
491
|
+
})
|
|
492
|
+
.cloned()
|
|
493
|
+
.collect()
|
|
494
|
+
} else {
|
|
495
|
+
self.elements
|
|
496
|
+
.keys()
|
|
497
|
+
.filter(|q| q.local == *name)
|
|
498
|
+
.cloned()
|
|
499
|
+
.collect()
|
|
500
|
+
};
|
|
501
|
+
match matches.as_slice() {
|
|
502
|
+
[] => return Err(format!("Root element '{name}' was not found in the schema")),
|
|
503
|
+
[qname] => {
|
|
504
|
+
selected_elements.insert(qname.clone());
|
|
505
|
+
}
|
|
506
|
+
_ => {
|
|
507
|
+
return Err(format!(
|
|
508
|
+
"Root element '{name}' is ambiguous; use {{namespace}}local-name"
|
|
509
|
+
))
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
let mut descendants: HashMap<QName, Vec<QName>> = HashMap::new();
|
|
515
|
+
for (qname, def) in &self.types {
|
|
516
|
+
let base = match def {
|
|
517
|
+
TypeDef::Struct(s) => s.base_type.as_ref(),
|
|
518
|
+
TypeDef::Simple(s) => named_ref(&s.base_type),
|
|
519
|
+
TypeDef::Enum(e) => named_ref(&e.base_type),
|
|
520
|
+
TypeDef::Union(_) => None,
|
|
521
|
+
};
|
|
522
|
+
if let Some(base) = base {
|
|
523
|
+
descendants
|
|
524
|
+
.entry(base.clone())
|
|
525
|
+
.or_default()
|
|
526
|
+
.push(qname.clone());
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
let mut selected_types = BTreeSet::new();
|
|
531
|
+
let mut pending_elements: Vec<_> = selected_elements.iter().cloned().collect();
|
|
532
|
+
let mut pending_types: Vec<(QName, bool)> = Vec::new();
|
|
533
|
+
let mut expanded_polymorphic = BTreeSet::new();
|
|
534
|
+
while !pending_elements.is_empty() || !pending_types.is_empty() {
|
|
535
|
+
while let Some(qname) = pending_elements.pop() {
|
|
536
|
+
if let Some(element) = self.elements.get(&qname) {
|
|
537
|
+
push_named_ref(&element.type_ref, true, &mut pending_types);
|
|
538
|
+
if let Some(head) = &element.substitution_group {
|
|
539
|
+
if selected_elements.insert(head.clone()) {
|
|
540
|
+
pending_elements.push(head.clone());
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if let Some(members) = self.substitution_groups.get(&qname) {
|
|
545
|
+
for member in members {
|
|
546
|
+
if selected_elements.insert(member.clone()) {
|
|
547
|
+
pending_elements.push(member.clone());
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if let Some((qname, polymorphic)) = pending_types.pop() {
|
|
553
|
+
if polymorphic && expanded_polymorphic.insert(qname.clone()) {
|
|
554
|
+
if let Some(children) = descendants.get(&qname) {
|
|
555
|
+
pending_types.extend(children.iter().cloned().map(|child| (child, true)));
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if !selected_types.insert(qname.clone()) {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
if let Some(def) = self.types.get(&qname) {
|
|
562
|
+
match def {
|
|
563
|
+
TypeDef::Struct(s) => {
|
|
564
|
+
if let Some(base) = &s.base_type {
|
|
565
|
+
pending_types.push((base.clone(), false));
|
|
566
|
+
}
|
|
567
|
+
for field in &s.fields {
|
|
568
|
+
push_named_ref(&field.type_ref, true, &mut pending_types);
|
|
569
|
+
if field.kind == FieldKind::Element {
|
|
570
|
+
let element = referenced_element_name(
|
|
571
|
+
field.namespace.as_deref(),
|
|
572
|
+
&field.xml_name,
|
|
573
|
+
);
|
|
574
|
+
if self.substitution_groups.contains_key(&element)
|
|
575
|
+
&& selected_elements.insert(element.clone())
|
|
576
|
+
{
|
|
577
|
+
pending_elements.push(element);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
TypeDef::Simple(s) => {
|
|
583
|
+
push_named_ref(&s.base_type, false, &mut pending_types)
|
|
584
|
+
}
|
|
585
|
+
TypeDef::Enum(e) => push_named_ref(&e.base_type, false, &mut pending_types),
|
|
586
|
+
TypeDef::Union(u) => {
|
|
587
|
+
for branch in &u.branches {
|
|
588
|
+
push_named_ref(&branch.type_ref, true, &mut pending_types);
|
|
589
|
+
let element = referenced_element_name(
|
|
590
|
+
branch.namespace.as_deref(),
|
|
591
|
+
&branch.xml_name,
|
|
592
|
+
);
|
|
593
|
+
if self.substitution_groups.contains_key(&element)
|
|
594
|
+
&& selected_elements.insert(element.clone())
|
|
595
|
+
{
|
|
596
|
+
pending_elements.push(element);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
let mut result = self.clone();
|
|
606
|
+
result
|
|
607
|
+
.types
|
|
608
|
+
.retain(|qname, _| selected_types.contains(qname));
|
|
609
|
+
result
|
|
610
|
+
.elements
|
|
611
|
+
.retain(|qname, _| selected_elements.contains(qname));
|
|
612
|
+
result
|
|
613
|
+
.external_types
|
|
614
|
+
.retain(|qname, _| selected_types.contains(qname));
|
|
615
|
+
result.substitution_groups.retain(|head, members| {
|
|
616
|
+
if !selected_elements.contains(head) {
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
members.retain(|member| selected_elements.contains(member));
|
|
620
|
+
!members.is_empty()
|
|
621
|
+
});
|
|
622
|
+
Ok(result)
|
|
623
|
+
}
|
|
624
|
+
|
|
470
625
|
pub fn is_external_type(&self, qname: &QName) -> bool {
|
|
471
626
|
if qname
|
|
472
627
|
.namespace
|
|
@@ -520,3 +675,165 @@ impl SchemaIR {
|
|
|
520
675
|
tarjan::resolve_cycles(self);
|
|
521
676
|
}
|
|
522
677
|
}
|
|
678
|
+
|
|
679
|
+
fn named_ref(type_ref: &TypeRef) -> Option<&QName> {
|
|
680
|
+
match type_ref {
|
|
681
|
+
TypeRef::Named(qname) => Some(qname),
|
|
682
|
+
TypeRef::Boxed(inner) | TypeRef::List(inner) => named_ref(inner),
|
|
683
|
+
TypeRef::Primitive(_) => None,
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
fn push_named_ref(type_ref: &TypeRef, polymorphic: bool, pending: &mut Vec<(QName, bool)>) {
|
|
688
|
+
if let Some(qname) = named_ref(type_ref) {
|
|
689
|
+
pending.push((qname.clone(), polymorphic));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
fn referenced_element_name(namespace: Option<&str>, xml_name: &str) -> QName {
|
|
694
|
+
let local = xml_name.rsplit(':').next().unwrap_or(xml_name);
|
|
695
|
+
QName::new(namespace, local)
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
#[cfg(test)]
|
|
699
|
+
mod root_selection_tests {
|
|
700
|
+
use super::*;
|
|
701
|
+
|
|
702
|
+
fn structure(name: &str, base: Option<&str>, fields: Vec<FieldDef>) -> TypeDef {
|
|
703
|
+
TypeDef::Struct(StructDef {
|
|
704
|
+
qname: QName::new(Some("urn:test"), name),
|
|
705
|
+
base_type: base.map(|name| QName::new(Some("urn:test"), name)),
|
|
706
|
+
is_abstract: false,
|
|
707
|
+
is_mixed: false,
|
|
708
|
+
fields,
|
|
709
|
+
documentation: None,
|
|
710
|
+
})
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
fn element(name: &str, ty: &str) -> ElementDef {
|
|
714
|
+
ElementDef {
|
|
715
|
+
qname: QName::new(Some("urn:test"), name),
|
|
716
|
+
type_ref: TypeRef::named(QName::new(Some("urn:test"), ty)),
|
|
717
|
+
substitution_group: None,
|
|
718
|
+
nillable: false,
|
|
719
|
+
documentation: None,
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
#[test]
|
|
724
|
+
fn keeps_references_descendants_and_substitutions() {
|
|
725
|
+
let mut ir = SchemaIR::new();
|
|
726
|
+
let mut field = FieldDef::new(
|
|
727
|
+
"item",
|
|
728
|
+
"Item",
|
|
729
|
+
FieldKind::Element,
|
|
730
|
+
TypeRef::List(Box::new(TypeRef::named(QName::new(
|
|
731
|
+
Some("urn:test"),
|
|
732
|
+
"Choice",
|
|
733
|
+
)))),
|
|
734
|
+
);
|
|
735
|
+
field.namespace = Some("urn:test".to_string());
|
|
736
|
+
ir.add_type(structure("RootType", None, vec![field]));
|
|
737
|
+
ir.add_type(structure("Base", None, vec![]));
|
|
738
|
+
ir.add_type(structure("Derived", Some("Base"), vec![]));
|
|
739
|
+
ir.add_type(TypeDef::Union(UnionDef {
|
|
740
|
+
qname: QName::new(Some("urn:test"), "Choice"),
|
|
741
|
+
branches: vec![UnionBranch {
|
|
742
|
+
variant_name: "Base".into(),
|
|
743
|
+
xml_name: "Base".into(),
|
|
744
|
+
namespace: Some("urn:test".into()),
|
|
745
|
+
type_ref: TypeRef::named(QName::new(Some("urn:test"), "Base")),
|
|
746
|
+
documentation: None,
|
|
747
|
+
}],
|
|
748
|
+
documentation: None,
|
|
749
|
+
}));
|
|
750
|
+
ir.add_type(structure("Unrelated", None, vec![]));
|
|
751
|
+
ir.add_element(element("Root", "RootType"));
|
|
752
|
+
ir.add_element(element("UnrelatedRoot", "Unrelated"));
|
|
753
|
+
let mut member = element("Member", "Derived");
|
|
754
|
+
member.substitution_group = Some(QName::new(Some("urn:test"), "Root"));
|
|
755
|
+
ir.add_element(member);
|
|
756
|
+
|
|
757
|
+
let selected = ir.select_root_elements(&["Root".into()]).unwrap();
|
|
758
|
+
assert_eq!(selected.elements.len(), 2);
|
|
759
|
+
assert_eq!(selected.types.len(), 4);
|
|
760
|
+
assert!(selected
|
|
761
|
+
.types
|
|
762
|
+
.contains_key(&QName::new(Some("urn:test"), "Derived")));
|
|
763
|
+
assert!(!selected
|
|
764
|
+
.types
|
|
765
|
+
.contains_key(&QName::new(Some("urn:test"), "Unrelated")));
|
|
766
|
+
let combined = ir
|
|
767
|
+
.select_root_elements(&["Root".into(), "UnrelatedRoot".into()])
|
|
768
|
+
.unwrap();
|
|
769
|
+
assert_eq!(combined.elements.len(), 3);
|
|
770
|
+
assert!(combined
|
|
771
|
+
.types
|
|
772
|
+
.contains_key(&QName::new(Some("urn:test"), "Unrelated")));
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
#[test]
|
|
776
|
+
fn rejects_missing_and_ambiguous_roots() {
|
|
777
|
+
let mut ir = SchemaIR::new();
|
|
778
|
+
ir.add_element(element("Root", "RootType"));
|
|
779
|
+
let mut second = element("Root", "RootType");
|
|
780
|
+
second.qname.namespace = Some("urn:other".into());
|
|
781
|
+
ir.add_element(second);
|
|
782
|
+
assert!(ir
|
|
783
|
+
.select_root_elements(&["Root".into()])
|
|
784
|
+
.unwrap_err()
|
|
785
|
+
.contains("ambiguous"));
|
|
786
|
+
assert_eq!(
|
|
787
|
+
ir.select_root_elements(&["{urn:test}Root".into()])
|
|
788
|
+
.unwrap()
|
|
789
|
+
.elements
|
|
790
|
+
.len(),
|
|
791
|
+
1
|
|
792
|
+
);
|
|
793
|
+
assert!(ir
|
|
794
|
+
.select_root_elements(&["Missing".into()])
|
|
795
|
+
.unwrap_err()
|
|
796
|
+
.contains("not found"));
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
#[test]
|
|
800
|
+
fn inherited_base_does_not_select_sibling_types() {
|
|
801
|
+
let mut ir = SchemaIR::new();
|
|
802
|
+
ir.add_type(structure("CommonBase", None, vec![]));
|
|
803
|
+
ir.add_type(structure("SelectedType", Some("CommonBase"), vec![]));
|
|
804
|
+
ir.add_type(structure("SiblingType", Some("CommonBase"), vec![]));
|
|
805
|
+
ir.add_element(element("Selected", "SelectedType"));
|
|
806
|
+
let selected = ir.select_root_elements(&["Selected".into()]).unwrap();
|
|
807
|
+
assert!(selected
|
|
808
|
+
.types
|
|
809
|
+
.contains_key(&QName::new(Some("urn:test"), "CommonBase")));
|
|
810
|
+
assert!(selected
|
|
811
|
+
.types
|
|
812
|
+
.contains_key(&QName::new(Some("urn:test"), "SelectedType")));
|
|
813
|
+
assert!(!selected
|
|
814
|
+
.types
|
|
815
|
+
.contains_key(&QName::new(Some("urn:test"), "SiblingType")));
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
#[test]
|
|
819
|
+
fn field_reference_keeps_substitution_group_members() {
|
|
820
|
+
let xsd = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
821
|
+
xmlns:t="urn:test" targetNamespace="urn:test" elementFormDefault="qualified">
|
|
822
|
+
<xs:element name="Head" type="xs:string" abstract="true"/>
|
|
823
|
+
<xs:element name="Member" type="xs:string" substitutionGroup="t:Head"/>
|
|
824
|
+
<xs:complexType name="ContainerType"><xs:sequence>
|
|
825
|
+
<xs:element ref="t:Head"/>
|
|
826
|
+
</xs:sequence></xs:complexType>
|
|
827
|
+
<xs:element name="Container" type="t:ContainerType"/>
|
|
828
|
+
</xs:schema>"#;
|
|
829
|
+
let mut parser = crate::schema_parser::XsdParser::new();
|
|
830
|
+
let ir = parser.parse_str(xsd).unwrap();
|
|
831
|
+
let selected = ir.select_root_elements(&["Container".into()]).unwrap();
|
|
832
|
+
assert!(selected
|
|
833
|
+
.elements
|
|
834
|
+
.contains_key(&QName::new(Some("urn:test"), "Head")));
|
|
835
|
+
assert!(selected
|
|
836
|
+
.elements
|
|
837
|
+
.contains_key(&QName::new(Some("urn:test"), "Member")));
|
|
838
|
+
}
|
|
839
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{polyxml-0.30.7 → polyxml-0.31.0}/crates/polyxml-core/benches/support/tag_dispatch_fixtures.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|