polyxml 0.33.6__tar.gz → 0.33.7__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.33.6 → polyxml-0.33.7}/Cargo.lock +6 -6
- {polyxml-0.33.6 → polyxml-0.33.7}/Cargo.toml +1 -1
- {polyxml-0.33.6 → polyxml-0.33.7}/PKG-INFO +1 -1
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/csharp/mod.rs +84 -4
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/go/mod.rs +1 -1
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/python/mod.rs +13 -2
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/parser.rs +49 -9
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/schema.rs +3 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_csharp_codegen.rs +46 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_python_codegen.rs +1 -1
- polyxml-0.33.7/crates/polyxml-core/tests/test_qualified_attributes.rs +80 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_security.rs +27 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/src/lib.rs +9 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/tests/test_generated_models.py +67 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/pyproject.toml +1 -1
- {polyxml-0.33.6 → polyxml-0.33.7}/README.md +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/Cargo.toml +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/README.md +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/benches/support/tag_dispatch_fixtures.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/benches/tag_dispatch.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/cpp/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/java/codec.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/java/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/java/models.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/python/aot.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/rust/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/codegen/typescript/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/converters.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/error.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/ir/chunker.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/ir/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/json.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/lib.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/schema_parser/mod.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/serializer.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/transcoder.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/src/value.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/fixtures/lexical_union.xsd +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/fixtures/mixed_content.xsd +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/fixtures/ts_mixed_content_inheritance.xsd +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_adversarial_identifiers.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_any_attribute.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_any_element.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_conformance.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_core.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_json.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_lexical_union_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_mixed_content.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_pattern_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_rust_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_schema_audit.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_unbounded_choice.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-core/tests/test_xsi_type.rs +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/Cargo.toml +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/README.md +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/benches/aot_vs_dataclass.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/tests/test_conformance.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/tests/test_json.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/tests/test_mixed_content.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/tests/test_polyxml.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/crates/polyxml-python/tests/test_xsi_type.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/python/polyxml/AGENT_GUIDE.md +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/python/polyxml/__init__.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/python/polyxml/compat/__init__.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/python/polyxml/compat/xsdata.py +0 -0
- {polyxml-0.33.6 → polyxml-0.33.7}/python/polyxml/py.typed +0 -0
|
@@ -608,7 +608,7 @@ dependencies = [
|
|
|
608
608
|
|
|
609
609
|
[[package]]
|
|
610
610
|
name = "polyxml"
|
|
611
|
-
version = "0.33.
|
|
611
|
+
version = "0.33.7"
|
|
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.33.
|
|
632
|
+
version = "0.33.7"
|
|
633
633
|
dependencies = [
|
|
634
634
|
"polyxml",
|
|
635
635
|
]
|
|
636
636
|
|
|
637
637
|
[[package]]
|
|
638
638
|
name = "polyxml-cli"
|
|
639
|
-
version = "0.33.
|
|
639
|
+
version = "0.33.7"
|
|
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.33.
|
|
653
|
+
version = "0.33.7"
|
|
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.33.
|
|
663
|
+
version = "0.33.7"
|
|
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.33.
|
|
673
|
+
version = "0.33.7"
|
|
674
674
|
dependencies = [
|
|
675
675
|
"polyxml",
|
|
676
676
|
"quick-xml",
|
|
@@ -869,6 +869,55 @@ impl CSharpCodegen {
|
|
|
869
869
|
let _ = writeln!(out, "{} }};", indent);
|
|
870
870
|
}
|
|
871
871
|
|
|
872
|
+
fn emit_default_scalar_proxy(
|
|
873
|
+
&self,
|
|
874
|
+
out: &mut String,
|
|
875
|
+
field: &FieldDef,
|
|
876
|
+
name: &str,
|
|
877
|
+
ir: &SchemaIR,
|
|
878
|
+
indent: &str,
|
|
879
|
+
) -> bool {
|
|
880
|
+
let Some(default) = field.default_value.as_ref() else {
|
|
881
|
+
return false;
|
|
882
|
+
};
|
|
883
|
+
if !self.options.emit_xml_attributes
|
|
884
|
+
|| field.kind != FieldKind::Element
|
|
885
|
+
|| field.cardinality.is_list()
|
|
886
|
+
|| matches!(field.type_ref, TypeRef::Named(ref q) if matches!(ir.types.get(q), Some(TypeDef::Struct(_) | TypeDef::Union(_))))
|
|
887
|
+
{
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
let ty = self.map_field_type(field, ir);
|
|
891
|
+
let base = ty.trim_end_matches('?');
|
|
892
|
+
let namespace = field
|
|
893
|
+
.namespace
|
|
894
|
+
.as_ref()
|
|
895
|
+
.map(|ns| format!(", Namespace = {ns:?}"))
|
|
896
|
+
.unwrap_or_default();
|
|
897
|
+
writeln!(
|
|
898
|
+
out,
|
|
899
|
+
"{indent} [XmlIgnore] public {ty} {name} {{ get; set; }} = default!;"
|
|
900
|
+
)
|
|
901
|
+
.unwrap();
|
|
902
|
+
writeln!(
|
|
903
|
+
out,
|
|
904
|
+
"{indent} [XmlElement({:?}{namespace})] public string? {name}Xml {{",
|
|
905
|
+
field.xml_name
|
|
906
|
+
)
|
|
907
|
+
.unwrap();
|
|
908
|
+
writeln!(out, "{indent} get {{ if ({name} is null) return null; var writer = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture); new XmlSerializer(typeof({base}), new XmlRootAttribute(\"value\")).Serialize(writer, {name}); return System.Xml.Linq.XDocument.Parse(writer.ToString()).Root!.Value; }}").unwrap();
|
|
909
|
+
writeln!(out, "{indent} set {{ if (value is null) {{ {name} = default!; return; }} var text = value.Length == 0 ? {default:?} : value; {name} = ({base})new XmlSerializer(typeof({base}), new XmlRootAttribute(\"value\")).Deserialize(new System.IO.StringReader(\"<value>\" + System.Security.SecurityElement.Escape(text) + \"</value>\"))!; }}
|
|
910
|
+
{indent} }}").unwrap();
|
|
911
|
+
if field.cardinality.is_optional() || field.nillable {
|
|
912
|
+
writeln!(
|
|
913
|
+
out,
|
|
914
|
+
"{indent} public bool ShouldSerialize{name}Xml() => {name} is not null;"
|
|
915
|
+
)
|
|
916
|
+
.unwrap();
|
|
917
|
+
}
|
|
918
|
+
true
|
|
919
|
+
}
|
|
920
|
+
|
|
872
921
|
fn emit_mixed_struct(
|
|
873
922
|
&self,
|
|
874
923
|
out: &mut String,
|
|
@@ -1030,7 +1079,7 @@ impl CSharpCodegen {
|
|
|
1030
1079
|
}
|
|
1031
1080
|
|
|
1032
1081
|
let has_lexical_union = self.options.emit_xml_attributes && s.fields.iter().any(|f| {
|
|
1033
|
-
matches!(&f.type_ref, TypeRef::Named(q) if matches!(ir.types.get(q), Some(TypeDef::Union(u)) if u.is_lexical()))
|
|
1082
|
+
f.default_value.is_some() || matches!(&f.type_ref, TypeRef::Named(q) if matches!(ir.types.get(q), Some(TypeDef::Union(u)) if u.is_lexical()))
|
|
1034
1083
|
});
|
|
1035
1084
|
|
|
1036
1085
|
if self.options.use_records && has_lexical_union {
|
|
@@ -1041,6 +1090,9 @@ impl CSharpCodegen {
|
|
|
1041
1090
|
)
|
|
1042
1091
|
.unwrap();
|
|
1043
1092
|
for (f, name) in s.fields.iter().zip(&prop_names) {
|
|
1093
|
+
if self.emit_default_scalar_proxy(out, f, name, ir, indent) {
|
|
1094
|
+
continue;
|
|
1095
|
+
}
|
|
1044
1096
|
let ty = self.map_field_type(f, ir);
|
|
1045
1097
|
if let TypeRef::Named(q) = &f.type_ref {
|
|
1046
1098
|
if matches!(ir.types.get(q), Some(TypeDef::Union(u)) if u.is_lexical()) {
|
|
@@ -1059,7 +1111,16 @@ impl CSharpCodegen {
|
|
|
1059
1111
|
} else {
|
|
1060
1112
|
"XmlElement"
|
|
1061
1113
|
};
|
|
1062
|
-
let
|
|
1114
|
+
let namespace = f
|
|
1115
|
+
.namespace
|
|
1116
|
+
.as_ref()
|
|
1117
|
+
.map(|ns| format!(", Namespace = {ns:?}"))
|
|
1118
|
+
.unwrap_or_default();
|
|
1119
|
+
let _ = writeln!(
|
|
1120
|
+
out,
|
|
1121
|
+
"{} [{}({:?}{namespace})]",
|
|
1122
|
+
indent, xml_kind, f.xml_name
|
|
1123
|
+
);
|
|
1063
1124
|
if self.options.emit_json_attributes {
|
|
1064
1125
|
let _ = writeln!(out, "{} [JsonIgnore]", indent);
|
|
1065
1126
|
}
|
|
@@ -1093,6 +1154,9 @@ impl CSharpCodegen {
|
|
|
1093
1154
|
.unwrap();
|
|
1094
1155
|
writeln!(out, "{} public {}() {{ }}", indent, struct_name).unwrap();
|
|
1095
1156
|
for (f, name) in s.fields.iter().zip(&prop_names) {
|
|
1157
|
+
if self.emit_default_scalar_proxy(out, f, name, ir, indent) {
|
|
1158
|
+
continue;
|
|
1159
|
+
}
|
|
1096
1160
|
let ty = self.map_field_type(f, ir);
|
|
1097
1161
|
if let TypeRef::Named(q) = &f.type_ref {
|
|
1098
1162
|
if self.options.emit_xml_attributes
|
|
@@ -1113,7 +1177,16 @@ impl CSharpCodegen {
|
|
|
1113
1177
|
} else {
|
|
1114
1178
|
"XmlElement"
|
|
1115
1179
|
};
|
|
1116
|
-
let
|
|
1180
|
+
let namespace = f
|
|
1181
|
+
.namespace
|
|
1182
|
+
.as_ref()
|
|
1183
|
+
.map(|ns| format!(", Namespace = {ns:?}"))
|
|
1184
|
+
.unwrap_or_default();
|
|
1185
|
+
let _ = writeln!(
|
|
1186
|
+
out,
|
|
1187
|
+
"{} [{}({:?}{namespace})]",
|
|
1188
|
+
indent, xml_kind, f.xml_name
|
|
1189
|
+
);
|
|
1117
1190
|
if self.options.emit_json_attributes {
|
|
1118
1191
|
let _ = writeln!(out, "{} [JsonIgnore]", indent);
|
|
1119
1192
|
}
|
|
@@ -1459,7 +1532,14 @@ impl CSharpCodegen {
|
|
|
1459
1532
|
}
|
|
1460
1533
|
if parts.is_empty() {
|
|
1461
1534
|
match f.kind {
|
|
1462
|
-
FieldKind::Attribute =>
|
|
1535
|
+
FieldKind::Attribute => {
|
|
1536
|
+
let namespace = f
|
|
1537
|
+
.namespace
|
|
1538
|
+
.as_ref()
|
|
1539
|
+
.map(|ns| format!(", Namespace = {ns:?}"))
|
|
1540
|
+
.unwrap_or_default();
|
|
1541
|
+
parts.push(format!("XmlAttribute({:?}{namespace})", f.xml_name));
|
|
1542
|
+
}
|
|
1463
1543
|
FieldKind::Text => parts.push("XmlText".to_string()),
|
|
1464
1544
|
FieldKind::Any => parts.push("XmlAnyElement".to_string()),
|
|
1465
1545
|
FieldKind::AnyAttribute => parts.push("XmlAnyAttribute".to_string()),
|
|
@@ -1230,7 +1230,7 @@ impl GoCodegen {
|
|
|
1230
1230
|
let xml_val = match f.kind {
|
|
1231
1231
|
FieldKind::Attribute => {
|
|
1232
1232
|
let attr_name = match &f.namespace {
|
|
1233
|
-
Some(ns) if !ns.is_empty()
|
|
1233
|
+
Some(ns) if !ns.is_empty() => {
|
|
1234
1234
|
format!("{} {}", ns, f.xml_name)
|
|
1235
1235
|
}
|
|
1236
1236
|
_ => f.xml_name.clone(),
|
|
@@ -840,7 +840,11 @@ impl PythonCodegen {
|
|
|
840
840
|
format!("field(default_factory=list, metadata={})", meta_dict),
|
|
841
841
|
)
|
|
842
842
|
} else if field.cardinality.is_optional() || field.nillable {
|
|
843
|
-
if let Some(
|
|
843
|
+
if let Some(def) = field
|
|
844
|
+
.default_value
|
|
845
|
+
.as_ref()
|
|
846
|
+
.filter(|_| field.kind == FieldKind::Attribute)
|
|
847
|
+
{
|
|
844
848
|
let py_val = self.format_default_value(def, &field.type_ref, ir);
|
|
845
849
|
(
|
|
846
850
|
format!("{} | None", base_type),
|
|
@@ -928,7 +932,11 @@ impl PythonCodegen {
|
|
|
928
932
|
format!("Field(default_factory=list, {})", extra_clause),
|
|
929
933
|
)
|
|
930
934
|
} else if field.cardinality.is_optional() || field.nillable {
|
|
931
|
-
if let Some(
|
|
935
|
+
if let Some(def) = field
|
|
936
|
+
.default_value
|
|
937
|
+
.as_ref()
|
|
938
|
+
.filter(|_| field.kind == FieldKind::Attribute)
|
|
939
|
+
{
|
|
932
940
|
let py_val = self.format_default_value(def, &field.type_ref, ir);
|
|
933
941
|
(
|
|
934
942
|
format!("{} | None", base_type),
|
|
@@ -985,6 +993,9 @@ impl PythonCodegen {
|
|
|
985
993
|
parts.push(format!("\"namespace\": \"{}\"", ns));
|
|
986
994
|
}
|
|
987
995
|
|
|
996
|
+
if let Some(ref default) = field.default_value {
|
|
997
|
+
parts.push(format!("\"default\": {default:?}"));
|
|
998
|
+
}
|
|
988
999
|
if field.nillable {
|
|
989
1000
|
parts.push("\"nillable\": True".to_string());
|
|
990
1001
|
}
|
|
@@ -7,7 +7,7 @@ use smallvec::{smallvec, SmallVec};
|
|
|
7
7
|
|
|
8
8
|
use crate::converters::ValueConverter;
|
|
9
9
|
use crate::error::{PolyXmlError, Result};
|
|
10
|
-
use crate::schema::{ModelSchema, ScalarType, ValueType};
|
|
10
|
+
use crate::schema::{FieldKind, ModelSchema, ScalarType, ValueType};
|
|
11
11
|
use crate::value::PolyValue;
|
|
12
12
|
|
|
13
13
|
type NamespaceScope = Arc<HashMap<String, String>>;
|
|
@@ -71,6 +71,19 @@ impl StackFrame {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
fn finish(mut self) -> Result<PolyValue> {
|
|
74
|
+
for (index, field) in self.schema.fields.iter().enumerate() {
|
|
75
|
+
if field.kind == FieldKind::Attribute && self.values[index].is_none() {
|
|
76
|
+
if let (Some(default), ValueType::Scalar(scalar)) =
|
|
77
|
+
(&field.default_value, &field.val_type)
|
|
78
|
+
{
|
|
79
|
+
self.values[index] = Some(ValueConverter::parse_scalar(
|
|
80
|
+
scalar,
|
|
81
|
+
default.as_bytes(),
|
|
82
|
+
&field.name,
|
|
83
|
+
)?);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
74
87
|
if !self.list_values.is_empty() {
|
|
75
88
|
for (idx, list_opt) in self.list_values.into_iter().enumerate() {
|
|
76
89
|
if let Some(list) = list_opt {
|
|
@@ -107,6 +120,22 @@ impl StackFrame {
|
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
|
|
123
|
+
fn parse_field_scalar(
|
|
124
|
+
scalar: &ScalarType,
|
|
125
|
+
text: &[u8],
|
|
126
|
+
field: &crate::schema::FieldSchema,
|
|
127
|
+
) -> Result<PolyValue> {
|
|
128
|
+
let text = if text.is_empty() && field.kind != FieldKind::Attribute {
|
|
129
|
+
field
|
|
130
|
+
.default_value
|
|
131
|
+
.as_ref()
|
|
132
|
+
.map_or(text, |value| value.as_bytes())
|
|
133
|
+
} else {
|
|
134
|
+
text
|
|
135
|
+
};
|
|
136
|
+
ValueConverter::parse_scalar(scalar, text, &field.name)
|
|
137
|
+
}
|
|
138
|
+
|
|
110
139
|
pub struct XmlDeserializer;
|
|
111
140
|
|
|
112
141
|
fn is_nil_element(e: &BytesStart) -> bool {
|
|
@@ -245,7 +274,10 @@ fn append_general_ref(
|
|
|
245
274
|
} else if let Some(s) = quick_xml::escape::resolve_xml_entity(e.as_ref()) {
|
|
246
275
|
s.as_bytes()
|
|
247
276
|
} else {
|
|
248
|
-
|
|
277
|
+
return Err(PolyXmlError::SchemaError(format!(
|
|
278
|
+
"Unsupported general entity reference: &{};",
|
|
279
|
+
e.as_ref()
|
|
280
|
+
)));
|
|
249
281
|
};
|
|
250
282
|
|
|
251
283
|
if active_scalar {
|
|
@@ -598,20 +630,20 @@ impl XmlDeserializer {
|
|
|
598
630
|
{
|
|
599
631
|
let field = ¤t_schema.fields[field_idx];
|
|
600
632
|
match &field.val_type {
|
|
601
|
-
ValueType::Scalar(
|
|
633
|
+
ValueType::Scalar(scalar) => {
|
|
602
634
|
let val = if is_nil {
|
|
603
635
|
PolyValue::Null
|
|
604
636
|
} else {
|
|
605
|
-
|
|
637
|
+
parse_field_scalar(scalar, b"", field)?
|
|
606
638
|
};
|
|
607
639
|
stack.last_mut().unwrap().values[field_idx] = Some(val);
|
|
608
640
|
}
|
|
609
641
|
ValueType::List(inner) => match inner.as_ref() {
|
|
610
|
-
ValueType::Scalar(
|
|
642
|
+
ValueType::Scalar(scalar) => {
|
|
611
643
|
let val = if is_nil {
|
|
612
644
|
PolyValue::Null
|
|
613
645
|
} else {
|
|
614
|
-
|
|
646
|
+
parse_field_scalar(scalar, b"", field)?
|
|
615
647
|
};
|
|
616
648
|
stack.last_mut().unwrap().push_list_item(field_idx, val);
|
|
617
649
|
}
|
|
@@ -779,6 +811,15 @@ impl XmlDeserializer {
|
|
|
779
811
|
}
|
|
780
812
|
}
|
|
781
813
|
Ok(Event::GeneralRef(ref e)) => {
|
|
814
|
+
// Entity validity is independent of whether a field is retained.
|
|
815
|
+
if !e.is_char_ref()
|
|
816
|
+
&& quick_xml::escape::resolve_xml_entity(e.as_ref()).is_none()
|
|
817
|
+
{
|
|
818
|
+
return Err(PolyXmlError::SchemaError(format!(
|
|
819
|
+
"Unsupported general entity reference: &{};",
|
|
820
|
+
e.as_ref()
|
|
821
|
+
)));
|
|
822
|
+
}
|
|
782
823
|
if unknown_depth > 0 {
|
|
783
824
|
continue;
|
|
784
825
|
}
|
|
@@ -848,9 +889,8 @@ impl XmlDeserializer {
|
|
|
848
889
|
} else if let Some((field_idx, ref scalar_type, is_list)) =
|
|
849
890
|
active_scalar_field.take()
|
|
850
891
|
{
|
|
851
|
-
let
|
|
852
|
-
let parsed_val =
|
|
853
|
-
ValueConverter::parse_scalar(scalar_type, &text_buf, field_name)?;
|
|
892
|
+
let field = &stack.last().unwrap().schema.fields[field_idx];
|
|
893
|
+
let parsed_val = parse_field_scalar(scalar_type, &text_buf, field)?;
|
|
854
894
|
let frame = stack.last_mut().unwrap();
|
|
855
895
|
if is_list {
|
|
856
896
|
frame.push_list_item(field_idx, parsed_val);
|
|
@@ -65,6 +65,7 @@ pub struct FieldSchema {
|
|
|
65
65
|
pub kind: FieldKind,
|
|
66
66
|
pub val_type: ValueType,
|
|
67
67
|
pub required: bool,
|
|
68
|
+
pub default_value: Option<String>,
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
impl FieldSchema {
|
|
@@ -81,6 +82,7 @@ impl FieldSchema {
|
|
|
81
82
|
kind,
|
|
82
83
|
val_type,
|
|
83
84
|
required: false,
|
|
85
|
+
default_value: None,
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
|
|
@@ -351,6 +353,7 @@ impl ModelSchema {
|
|
|
351
353
|
}
|
|
352
354
|
|
|
353
355
|
let mut field_schema = FieldSchema::new(&f.name, f.xml_name.as_bytes(), kind, val_type);
|
|
356
|
+
field_schema.default_value = f.default_value.clone();
|
|
354
357
|
if let Some(ref ns) = f.namespace {
|
|
355
358
|
field_schema = field_schema.namespace(ns);
|
|
356
359
|
}
|
|
@@ -1232,3 +1232,49 @@ fn test_csharp_sequence_nested_inside_choice_codegen() {
|
|
|
1232
1232
|
assert!(code.contains("string? Alternative = null"));
|
|
1233
1233
|
assert!(code.contains("public record RootTypeSequence"));
|
|
1234
1234
|
}
|
|
1235
|
+
|
|
1236
|
+
#[test]
|
|
1237
|
+
fn element_defaults_preserve_absence_and_empty_presence() {
|
|
1238
|
+
let ir = polyxml::schema_parser::XsdParser::new()
|
|
1239
|
+
.parse_str(include_str!(
|
|
1240
|
+
"../../../research/fixtures/element_defaults.xsd"
|
|
1241
|
+
))
|
|
1242
|
+
.unwrap();
|
|
1243
|
+
for use_records in [true, false] {
|
|
1244
|
+
let temp = tempdir().unwrap();
|
|
1245
|
+
fs::write(temp.path().join("App.csproj"), r#"<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup></Project>"#).unwrap();
|
|
1246
|
+
fs::write(
|
|
1247
|
+
temp.path().join("Models.cs"),
|
|
1248
|
+
CSharpCodegen::new(CSharpOptions {
|
|
1249
|
+
namespace: "Models".into(),
|
|
1250
|
+
use_records,
|
|
1251
|
+
..Default::default()
|
|
1252
|
+
})
|
|
1253
|
+
.generate_module(&ir),
|
|
1254
|
+
)
|
|
1255
|
+
.unwrap();
|
|
1256
|
+
fs::write(temp.path().join("Program.cs"), r#"using Models;using System.Xml.Serialization;
|
|
1257
|
+
var serializer=new XmlSerializer(typeof(Root));
|
|
1258
|
+
foreach(var document in new[]{"<Root/>","<Root><Flag/><Count></Count><Label/></Root>"}){
|
|
1259
|
+
var root=(Root)serializer.Deserialize(new StringReader(document))!;
|
|
1260
|
+
var present=document.Contains("Flag");
|
|
1261
|
+
if(present&&(root.Flag!=false||root.Count!=42||root.Label!="fallback"))throw new Exception("defaults missing");
|
|
1262
|
+
if(!present&&(root.Flag!=null||root.Count!=null||root.Label!=null))throw new Exception("absence lost");
|
|
1263
|
+
var writer=new StringWriter();serializer.Serialize(writer,root);
|
|
1264
|
+
if(!present&&writer.ToString().Contains("<Flag"))throw new Exception("absent value serialized");
|
|
1265
|
+
if(present&&!writer.ToString().Contains("<Flag>false</Flag>"))throw new Exception(writer.ToString());
|
|
1266
|
+
}"#).unwrap();
|
|
1267
|
+
let _lock = DOTNET_LOCK.lock().unwrap();
|
|
1268
|
+
let result = dotnet_command()
|
|
1269
|
+
.arg("run")
|
|
1270
|
+
.current_dir(temp.path())
|
|
1271
|
+
.output()
|
|
1272
|
+
.unwrap();
|
|
1273
|
+
assert!(
|
|
1274
|
+
result.status.success(),
|
|
1275
|
+
"{}{}",
|
|
1276
|
+
String::from_utf8_lossy(&result.stdout),
|
|
1277
|
+
String::from_utf8_lossy(&result.stderr)
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
@@ -162,7 +162,7 @@ fn test_python_dataclass_codegen() {
|
|
|
162
162
|
// Check fields
|
|
163
163
|
assert!(code.contains("id: int = field(metadata={\"type\": \"Attribute\", \"name\": \"id\", \"json_name\": \"id\"})"));
|
|
164
164
|
assert!(code.contains("type_: str | None = field(default=None, metadata={\"type\": \"Element\", \"name\": \"type\", \"json_name\": \"type\", \"namespace\": \"https://example.com/shop\", \"nillable\": True})"));
|
|
165
|
-
assert!(code.contains("status: OrderStatus = field(default=\"pending\", metadata={\"type\": \"Element\", \"name\": \"status\", \"json_name\": \"status\"})"));
|
|
165
|
+
assert!(code.contains("status: OrderStatus = field(default=\"pending\", metadata={\"type\": \"Element\", \"name\": \"status\", \"json_name\": \"status\", \"default\": \"pending\"})"));
|
|
166
166
|
assert!(code.contains("tags: list[str] = field(default_factory=list, metadata={\"type\": \"Element\", \"name\": \"tag\", \"json_name\": \"tag\"})"));
|
|
167
167
|
}
|
|
168
168
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
use polyxml::codegen::{
|
|
2
|
+
csharp::{CSharpCodegen, CSharpOptions},
|
|
3
|
+
go::{GoCodegen, GoOptions},
|
|
4
|
+
};
|
|
5
|
+
use polyxml::schema_parser::XsdParser;
|
|
6
|
+
use std::{fs, process::Command};
|
|
7
|
+
use tempfile::tempdir;
|
|
8
|
+
|
|
9
|
+
#[test]
|
|
10
|
+
fn global_attribute_references_round_trip_by_namespace() {
|
|
11
|
+
let mut parser = XsdParser::new();
|
|
12
|
+
let ir = parser
|
|
13
|
+
.parse_file(concat!(
|
|
14
|
+
env!("CARGO_MANIFEST_DIR"),
|
|
15
|
+
"/../../research/fixtures/wave6/xlink_shared_attribute/root.xsd"
|
|
16
|
+
))
|
|
17
|
+
.unwrap();
|
|
18
|
+
let temp = tempdir().unwrap();
|
|
19
|
+
fs::write(temp.path().join("go.mod"), "module attrs\n\ngo 1.22\n").unwrap();
|
|
20
|
+
fs::write(
|
|
21
|
+
temp.path().join("models.go"),
|
|
22
|
+
GoCodegen::new(GoOptions::default()).generate_module(&ir),
|
|
23
|
+
)
|
|
24
|
+
.unwrap();
|
|
25
|
+
fs::write(temp.path().join("models_test.go"), r#"package models
|
|
26
|
+
import("encoding/xml";"testing";"strings";"io")
|
|
27
|
+
func TestAttributes(t *testing.T) {
|
|
28
|
+
for _, document := range []string{`<Links xmlns:xl="http://www.w3.org/1999/xlink"><Resource xl:type="resource"/><Arc xl:type="arc"/></Links>`, `<Links><Resource xmlns:other="http://www.w3.org/1999/xlink" other:type="resource"/><Arc xmlns:a="http://www.w3.org/1999/xlink" a:type="arc"/></Links>`} {
|
|
29
|
+
var root Links; if err:=xml.Unmarshal([]byte(document),&root);err!=nil{t.Fatal(err)}
|
|
30
|
+
data,err:=xml.Marshal(root);if err!=nil{t.Fatal(err)}
|
|
31
|
+
decoder:=xml.NewDecoder(strings.NewReader(string(data)));count:=0
|
|
32
|
+
for {token,err:=decoder.Token();if err==io.EOF{break};if err!=nil{t.Fatal(err)};if start,ok:=token.(xml.StartElement);ok{for _,attr:=range start.Attr{if attr.Name.Space=="http://www.w3.org/1999/xlink"&&attr.Name.Local=="type"{count++;if attr.Value!="resource"&&attr.Value!="arc"{t.Fatal(attr)}}}}}
|
|
33
|
+
if count!=2{t.Fatalf("attributes lost: %s",data)}
|
|
34
|
+
}
|
|
35
|
+
}"#).unwrap();
|
|
36
|
+
let result = Command::new("go")
|
|
37
|
+
.args(["test", "./..."])
|
|
38
|
+
.current_dir(temp.path())
|
|
39
|
+
.output()
|
|
40
|
+
.unwrap();
|
|
41
|
+
assert!(
|
|
42
|
+
result.status.success(),
|
|
43
|
+
"{}{}",
|
|
44
|
+
String::from_utf8_lossy(&result.stdout),
|
|
45
|
+
String::from_utf8_lossy(&result.stderr)
|
|
46
|
+
);
|
|
47
|
+
for use_records in [true, false] {
|
|
48
|
+
let temp = tempdir().unwrap();
|
|
49
|
+
fs::write(temp.path().join("App.csproj"), r#"<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup></Project>"#).unwrap();
|
|
50
|
+
fs::write(
|
|
51
|
+
temp.path().join("Models.cs"),
|
|
52
|
+
CSharpCodegen::new(CSharpOptions {
|
|
53
|
+
namespace: "Models".into(),
|
|
54
|
+
use_records,
|
|
55
|
+
..Default::default()
|
|
56
|
+
})
|
|
57
|
+
.generate_module(&ir),
|
|
58
|
+
)
|
|
59
|
+
.unwrap();
|
|
60
|
+
fs::write(temp.path().join("Program.cs"), r#"using System.Xml.Serialization;using System.Xml.Linq;using Models;
|
|
61
|
+
var serializer=new XmlSerializer(typeof(Links));
|
|
62
|
+
foreach(var document in new[]{"<Links xmlns:xl='http://www.w3.org/1999/xlink'><Resource xl:type='resource'/><Arc xl:type='arc'/></Links>","<Links><Resource xmlns:b='http://www.w3.org/1999/xlink' b:type='resource'/><Arc xmlns:c='http://www.w3.org/1999/xlink' c:type='arc'/></Links>"}){
|
|
63
|
+
var root=(Links)serializer.Deserialize(new StringReader(document))!;
|
|
64
|
+
var writer=new StringWriter();serializer.Serialize(writer,root);
|
|
65
|
+
var xml=XDocument.Parse(writer.ToString());XNamespace ns="http://www.w3.org/1999/xlink";
|
|
66
|
+
if((string?)xml.Root!.Element("Resource")!.Attribute(ns+"type")!="resource"||(string?)xml.Root.Element("Arc")!.Attribute(ns+"type")!="arc")throw new Exception(writer.ToString());
|
|
67
|
+
}"#).unwrap();
|
|
68
|
+
let result = Command::new("dotnet")
|
|
69
|
+
.arg("run")
|
|
70
|
+
.current_dir(temp.path())
|
|
71
|
+
.output()
|
|
72
|
+
.unwrap();
|
|
73
|
+
assert!(
|
|
74
|
+
result.status.success(),
|
|
75
|
+
"{}{}",
|
|
76
|
+
String::from_utf8_lossy(&result.stdout),
|
|
77
|
+
String::from_utf8_lossy(&result.stderr)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -162,3 +162,30 @@ fn test_malformed_unclosed_cdata_rejection() {
|
|
|
162
162
|
let bad_xml = br#"<Doc><body><![CDATA[unclosed cdata</body></Doc>"#;
|
|
163
163
|
assert!(deserialize(bad_xml, schema).is_err());
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
#[test]
|
|
167
|
+
fn unsupported_general_entities_are_rejected() {
|
|
168
|
+
let schema = ModelSchema::builder("Document")
|
|
169
|
+
.field(FieldSchema::new(
|
|
170
|
+
"payload",
|
|
171
|
+
b"Payload",
|
|
172
|
+
FieldKind::Element,
|
|
173
|
+
ValueType::Scalar(ScalarType::String),
|
|
174
|
+
))
|
|
175
|
+
.build();
|
|
176
|
+
for xml in [
|
|
177
|
+
"<Document><Payload>&audit;</Payload></Document>",
|
|
178
|
+
"<!DOCTYPE Document [<!ENTITY audit 'EXPECTED'>]><Document><Payload>&audit;</Payload></Document>",
|
|
179
|
+
"<!DOCTYPE Document [<!ENTITY audit SYSTEM 'file:///nonexistent/sentinel'>]><Document><Payload>&audit;</Payload></Document>",
|
|
180
|
+
"<Document><Unknown>&audit;</Unknown></Document>",
|
|
181
|
+
] {
|
|
182
|
+
let error = deserialize(xml.as_bytes(), Arc::clone(&schema)).unwrap_err();
|
|
183
|
+
assert!(error.to_string().contains("Unsupported general entity reference"), "{error}");
|
|
184
|
+
}
|
|
185
|
+
let value = deserialize(
|
|
186
|
+
b"<Document><Payload>&AB</Payload></Document>",
|
|
187
|
+
schema,
|
|
188
|
+
)
|
|
189
|
+
.unwrap();
|
|
190
|
+
assert_eq!(value.get("payload"), Some(&PolyValue::String("&AB".into())));
|
|
191
|
+
}
|
|
@@ -417,6 +417,10 @@ fn extract_schema_from_class<'py>(
|
|
|
417
417
|
});
|
|
418
418
|
|
|
419
419
|
let mut field_schema = FieldSchema::new(py_name, xml_name.as_bytes(), kind, val_type);
|
|
420
|
+
field_schema.default_value = meta
|
|
421
|
+
.as_ref()
|
|
422
|
+
.and_then(|m| m.get_item("default").ok())
|
|
423
|
+
.and_then(|v| v.extract::<String>().ok());
|
|
420
424
|
if let Some(ns) = field_ns {
|
|
421
425
|
field_schema = field_schema.namespace(ns);
|
|
422
426
|
}
|
|
@@ -494,6 +498,11 @@ fn extract_schema_from_class<'py>(
|
|
|
494
498
|
});
|
|
495
499
|
|
|
496
500
|
let mut field_schema = FieldSchema::new(py_name, xml_name.as_bytes(), kind, val_type);
|
|
501
|
+
field_schema.default_value = field_obj
|
|
502
|
+
.getattr("metadata")
|
|
503
|
+
.ok()
|
|
504
|
+
.and_then(|m| m.get_item("default").ok())
|
|
505
|
+
.and_then(|v| v.extract::<String>().ok());
|
|
497
506
|
if let Some(ns) = field_ns {
|
|
498
507
|
field_schema = field_schema.namespace(ns);
|
|
499
508
|
}
|
|
@@ -531,3 +531,70 @@ def test_codecs_flag_disabled():
|
|
|
531
531
|
mod = _load_module_from_file("gen_no_codecs", out_dir / "warehouse.py")
|
|
532
532
|
assert not hasattr(mod.Inventory, "from_xml")
|
|
533
533
|
assert not hasattr(mod.Inventory, "to_xml")
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
@pytest.mark.parametrize("backend", ["dataclass", "pydantic"])
|
|
537
|
+
def test_generated_models_reject_general_entities(tmp_path, backend):
|
|
538
|
+
schema = pathlib.Path(__file__).resolve().parents[3] / "research/fixtures/wave7/xxe_text.xsd"
|
|
539
|
+
subprocess.run(
|
|
540
|
+
[
|
|
541
|
+
str(_get_polyxml_bin()),
|
|
542
|
+
"generate",
|
|
543
|
+
str(schema),
|
|
544
|
+
"--lang",
|
|
545
|
+
"python",
|
|
546
|
+
"--backend",
|
|
547
|
+
backend,
|
|
548
|
+
"--out",
|
|
549
|
+
str(tmp_path),
|
|
550
|
+
],
|
|
551
|
+
check=True,
|
|
552
|
+
capture_output=True,
|
|
553
|
+
)
|
|
554
|
+
module = _load_module_from_file(f"entities_{backend}", tmp_path / "xxe_text.py")
|
|
555
|
+
sentinel = tmp_path / "sentinel.txt"
|
|
556
|
+
sentinel.write_text("PRIVATE_SENTINEL_VALUE")
|
|
557
|
+
for declaration in [
|
|
558
|
+
"",
|
|
559
|
+
"<!DOCTYPE Document [<!ENTITY audit 'EXPECTED'>]>",
|
|
560
|
+
f"<!DOCTYPE Document [<!ENTITY audit SYSTEM '{sentinel.as_uri()}'>]>",
|
|
561
|
+
]:
|
|
562
|
+
with pytest.raises(ValueError, match="Unsupported general entity reference"):
|
|
563
|
+
module.Document.from_xml(
|
|
564
|
+
declaration + "<Document><Payload>&audit;</Payload></Document>"
|
|
565
|
+
)
|
|
566
|
+
model = module.Document.from_xml("<Document><Payload>&AB</Payload></Document>")
|
|
567
|
+
assert model.payload == "&AB"
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
@pytest.mark.parametrize("backend", ["dataclass", "pydantic"])
|
|
571
|
+
def test_element_defaults_preserve_absence(tmp_path, backend):
|
|
572
|
+
schema = pathlib.Path(__file__).resolve().parents[3] / "research/fixtures/element_defaults.xsd"
|
|
573
|
+
subprocess.run(
|
|
574
|
+
[
|
|
575
|
+
str(_get_polyxml_bin()),
|
|
576
|
+
"generate",
|
|
577
|
+
str(schema),
|
|
578
|
+
"--lang",
|
|
579
|
+
"python",
|
|
580
|
+
"--backend",
|
|
581
|
+
backend,
|
|
582
|
+
"--out",
|
|
583
|
+
str(tmp_path),
|
|
584
|
+
],
|
|
585
|
+
check=True,
|
|
586
|
+
capture_output=True,
|
|
587
|
+
)
|
|
588
|
+
module = _load_module_from_file(f"defaults_{backend}", tmp_path / "element_defaults.py")
|
|
589
|
+
absent = module.Root.from_xml("<Root/>")
|
|
590
|
+
assert (absent.flag, absent.count, absent.label, absent.mode) == (None, None, None, "auto")
|
|
591
|
+
assert ET.fromstring(absent.to_xml()).find("Flag") is None
|
|
592
|
+
for document in [
|
|
593
|
+
"<Root><Flag/><Count></Count><Label/></Root>",
|
|
594
|
+
"<Root><Flag></Flag><Count/><Label></Label></Root>",
|
|
595
|
+
]:
|
|
596
|
+
present = module.Root.from_xml(document)
|
|
597
|
+
assert (present.flag, present.count, present.label) == (False, 42, "fallback")
|
|
598
|
+
encoded = present.to_xml()
|
|
599
|
+
assert ET.fromstring(encoded).findtext("Flag") == "false"
|
|
600
|
+
assert module.Root.from_xml(encoded).count == 42
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{polyxml-0.33.6 → polyxml-0.33.7}/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
|