xso: add support for ignoring unknown stuff in extracts
This commit is contained in:
parent
66233b0150
commit
7d8ffe45a7
4 changed files with 70 additions and 1 deletions
|
@ -1863,3 +1863,39 @@ fn ignore_unknown_children_negative_unexpected_attribute() {
|
|||
other => panic!("unexpected result: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = NS1, name = "parent")]
|
||||
struct ExtractIgnoreUnknownStuff {
|
||||
#[xml(extract(namespace = NS1, name = "child", on_unknown_attribute = Discard, on_unknown_child = Discard, fields(
|
||||
extract(namespace = NS1, name = "grandchild", fields(text))
|
||||
)))]
|
||||
contents: String,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_ignore_unknown_stuff_positive() {
|
||||
#[allow(unused_imports)]
|
||||
use std::{
|
||||
option::Option::{None, Some},
|
||||
result::Result::{Err, Ok},
|
||||
};
|
||||
match parse_str::<ExtractIgnoreUnknownStuff>(
|
||||
"<parent xmlns='urn:example:ns1'><child foo='bar'><quak/><grandchild>hello world</grandchild></child></parent>",
|
||||
) {
|
||||
Ok(ExtractIgnoreUnknownStuff { contents }) => {
|
||||
assert_eq!(contents, "hello world");
|
||||
}
|
||||
other => panic!("unexpected result: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_ignore_unknown_stuff_roundtrip() {
|
||||
#[allow(unused_imports)]
|
||||
use std::{
|
||||
option::Option::{None, Some},
|
||||
result::Result::{Err, Ok},
|
||||
};
|
||||
roundtrip_full::<ExtractIgnoreUnknownStuff>("<parent xmlns='urn:example:ns1'><child><grandchild>hello world</grandchild></child></parent>")
|
||||
}
|
||||
|
|
|
@ -319,6 +319,8 @@ fn new_field(
|
|||
qname: QNameRef { namespace, name },
|
||||
amount,
|
||||
fields,
|
||||
on_unknown_attribute,
|
||||
on_unknown_child,
|
||||
} => {
|
||||
let xml_namespace = namespace.unwrap_or_else(|| container_namespace.clone());
|
||||
let xml_name = default_name(span, name, field_ident)?;
|
||||
|
@ -366,7 +368,8 @@ fn new_field(
|
|||
&xml_namespace,
|
||||
));
|
||||
}
|
||||
let parts = Compound::from_field_defs(field_defs, None, None)?;
|
||||
let parts =
|
||||
Compound::from_field_defs(field_defs, on_unknown_attribute, on_unknown_child)?;
|
||||
|
||||
Ok(Box::new(ChildField {
|
||||
default_,
|
||||
|
|
|
@ -737,6 +737,12 @@ pub(crate) enum XmlFieldMeta {
|
|||
|
||||
/// The `fields` nested meta.
|
||||
fields: Vec<XmlFieldMeta>,
|
||||
|
||||
/// The `on_unknown_attribute` value.
|
||||
on_unknown_attribute: Option<Ident>,
|
||||
|
||||
/// The `on_unknown_child` value.
|
||||
on_unknown_child: Option<Ident>,
|
||||
},
|
||||
|
||||
/// `#[xml(element)]`
|
||||
|
@ -925,6 +931,8 @@ impl XmlFieldMeta {
|
|||
let mut qname = QNameRef::default();
|
||||
let mut fields = None;
|
||||
let mut amount = None;
|
||||
let mut on_unknown_attribute = None;
|
||||
let mut on_unknown_child = None;
|
||||
let mut default_ = Flag::Absent;
|
||||
meta.parse_nested_meta(|meta| {
|
||||
if meta.path.is_ident("default") {
|
||||
|
@ -952,6 +960,24 @@ impl XmlFieldMeta {
|
|||
}
|
||||
amount = Some(meta.value()?.parse()?);
|
||||
Ok(())
|
||||
} else if meta.path.is_ident("on_unknown_attribute") {
|
||||
if on_unknown_attribute.is_some() {
|
||||
return Err(Error::new_spanned(
|
||||
meta.path,
|
||||
"duplicate `on_unknown_attribute` key",
|
||||
));
|
||||
}
|
||||
on_unknown_attribute = Some(meta.value()?.parse()?);
|
||||
Ok(())
|
||||
} else if meta.path.is_ident("on_unknown_child") {
|
||||
if on_unknown_child.is_some() {
|
||||
return Err(Error::new_spanned(
|
||||
meta.path,
|
||||
"duplicate `on_unknown_child` key",
|
||||
));
|
||||
}
|
||||
on_unknown_child = Some(meta.value()?.parse()?);
|
||||
Ok(())
|
||||
} else {
|
||||
match qname.parse_incremental_from_meta(meta)? {
|
||||
None => Ok(()),
|
||||
|
@ -966,6 +992,8 @@ impl XmlFieldMeta {
|
|||
qname,
|
||||
fields,
|
||||
amount,
|
||||
on_unknown_attribute,
|
||||
on_unknown_child,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -474,6 +474,8 @@ The following keys can be used inside the `#[xml(extract(..))]` meta:
|
|||
| `default` | flag | If present, an absent child will substitute the default value instead of raising an error. |
|
||||
| `n` | `1` or `..` | If `1`, a single element is parsed. If `..`, a collection is parsed. Defaults to `1`. |
|
||||
| `fields` | *nested* | A list of [field meta](#field-meta) which describe the contents of the child element. |
|
||||
| `on_unknown_attribute` | *identifier* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
|
||||
| `on_unknown_child` | *identifier* | Name of an [`UnknownChildPolicy`] member, controlling how unknown children are handled. |
|
||||
|
||||
If the `name` key contains a namespace prefix, it must be one of the prefixes
|
||||
defined as built-in in the XML specifications. That prefix will then be
|
||||
|
|
Loading…
Reference in a new issue