#[derive(FromXml)]
{
// Attributes available to this derive:
#[xml]
}
Expand description
§Make a struct or enum parseable from XML
This macro generates the necessary trait implementations to convert a struct from XML.
In order to work, structs, enums, enum variants and fields all must be
annotated using the #[xml(..)]
meta. The insides of that meta are explained
below.
§Examples
static MY_NAMESPACE: &'static str = "urn:uuid:55c56882-3915-49de-a7ee-fd672d7a85cf";
#[derive(FromXml)]
#[xml(namespace = MY_NAMESPACE, name = "foo")]
struct Foo;
// parses <foo xmlns="urn:uuid:55c56882-3915-49de-a7ee-fd672d7a85cf"/>
§Field order
Field order matters. The fields are parsed in the order they are declared
(for children, anyway). If multiple fields match a given child element, the
first field which matches will be taken. The only exception is
#[xml(elements)]
(without further arguments), which is always processed
last.
When XML is generated from a struct, the child elements are also generated in the order of the fields. That means that passing an XML element through FromXml and IntoXml may re-order some child elements.
Sorting order between elements which match the same field is generally preserved, if the container preserves sort order on insertion.
§Struct attributes
-
namespace = ..
: This can be one of the following:-
dyn
: allows dynamic namespace matching using theDynNamespaceEnum
trait. A struct with this namespace type needs to have exactly one field with the#[xml(namespace)]
annotation.The type of that field must implement
DynNamespaceEnum
and will be used to match the namespace of the XML elements. -
A path referring to a
&'static str
static
which contains the namespace URI of the XML element represented by the struct.
Required on non-
transparent
structs. -
-
name = ..
: A string literal which contains the local XML name of of the XML element represented by the struct.Required on non-
transparent
structs. -
validate = ..
: A path referring to afn(&mut T) -> Result<(), xso::error::Error>
, whereT
is the struct which is being defined. If set, the function will be called after parsing has completed. If it returns an error, that error is returned instead of the struct.This attribute has no influence on
IntoXml
. -
prepare = ..
: A path referring to afn(&mut T) -> ()
, whereT
is the struct which is being defined. If set, the function will be called before the struct is converted into Element.This attribute has no influence on
FromXml
. -
transparent
: Only allowed on tuple-like structs with exactly one field. If set, the parsing is fully delegated to the inner field, which must in turn implementFromXml
(orIntoXml
respectively).Attributes on the single struct field are rejected.
validate
is allowed and will be called. -
element
,element(..): Only allowed on tuple-like structs with exactly one field. That field must be of type [
minidom::Element`].Supports the following optional inner attributes:
-
namespace
: If given, restricts the namespace of the elements to parse. Has no influence on XML generation: If the inner element has a different namespace when the struct is serialized, that namespace will be used. -
name
: If given, restricts the XML name of the elements to parse. Has no influence on XML generation: If the inner element has a different XML name when the struct is serialized, that namespace will be used.
validate
is allowed and will be called. -
-
on_unknown_child = ..
may be set to the identifier of a member of theUnknownChildPolicy
enum (i.e. for exampleon_unknown_child = Ignore
). This configures the behavior when unknown child elements are encountered. SeeUnknownChildPolicy
for details.Has no effect on grandchildren.
-
on_unknown_attribute = ..
may be set to the identifier of a member of theUnknownAttributePolicy
enum (i.e. for exampleon_unknown_attribute = Ignore
). This configures the behavior when unknown attributes are encountered. SeeUnknownAttributePolicy
for details.Has no effect on children.
-
wrapped_with(namespace = .., name = ..)
: If set, the struct will be wrapped into an XML element with the given namespace and name. That means that instead of<inner/>
, on the wire,<outer><inner/></outer>
(with the corresponding XML names and namespaces) is expected and generated.Other than the struct itself, the wrapping element must not have any attributes or child elements, and it only supports static namespaces.
§Enums
Enums come in multiple flavors. All flavors have the following attributes:
validate = ..
: See struct attributes.prepare = ..
: See struct attributes.wrapped_with = ..
: See struct attributes.
The following flavors exist:
-
fully dynamic: The variants must be each either transparent or specify their
namespace
andname
. -
XML name matched: The enum itself defines a namespace. Each variant must then specify the name. The variant is picked based on the name of the XML element.
-
XML attribute matched: The enum itself defines a namespace, a name and an attribute name. Each variant must specify the attribute value. The variant is picked based on the value of the given attribute, provided that XML name and namespace of the element itself match.
The flavor is determined based on the attributes of the enum declaration.
§Dynamic enums
No additional attributes are available on dynamic enumerations.
§Dynamic enum variants
Dynamic enum variants work exactly like structs, except that the prepare
and validate
attributes are not available.
§XML name matched enums
XML name matched enums support the following attributes:
-
namespace = ..
(required): This must be a path to a&'static str
. It is the namespace of the enumeration. -
exhaustive
(flag): If present, the enum considers itself authoritative for that namespace. If it encounters an element within the namespace which does not match any variant, a fatal parsing error is returned.This cannot be used if a variant is set as
fallback
.This attribute has no relation to the Rust standard
#[non_exhaustive]
attribute.
§XML name matched enum variants
XML name matched enum variants support the following attributes:
-
name = ..
(required): String literal with the XML name to match against. -
fallback
(flag): If present, the variant is parsed when no other variant matches.Note: When the enum is reserialized to XML, the XML name will be the one declared in the
name
attribute of the variant; the original XML name is lost.
§XML attribute matched enums
XML attribute matched enums support the following attributes:
-
namespace = ..
(required): This must be a path to a&'static str
. It is the namespace of the enumeration. -
name = ..
(required): This must be a string literal containing the XML name to match against. -
attribute = ..
(required): This must be a string literal with the name of the XML attribute to match against. -
exhaustive
(flag): Must currently be set unless a variant is marked asfallback
. Support for non-exhaustive attribute-matched enums is not implemented yet.This cannot be used if a variant is set as
fallback
.This attribute has no relation to the Rust standard
#[non_exhaustive]
attribute. -
normalize_with = ..
: Optional path to a thing which can be called with a&str
and which returns astd::borrow::Cow
. If present, the attribute value will be passed through that callable before it will be matched against the enum variants.
§XML attribute matched enum variants
XML attribute matched enum variants support the following attributes:
-
value = ..
(required): String literal with the attribute value to match against. -
fallback
(flag): If present, the variant is parsed when no other variant matches.Note: When the enum is reserialized to XML, the attribute value will be the one declared in the
value
attribute of the variant; the original value is lost.
§Field attributes
Field attributes are composed of a field kind, followed by a value or a list of attributes. Examples:
#[xml(attribute)]
#[xml(attribute = "foo")]
#[xml(attribute(name = "foo"))]
If the kind = ..
syntax is allowed, the attribute which is specified that
way will be marked as default
.
The following field kinds are available:
-
attribute
,attribute = name
,attribute(..)
: Extract a string from an XML attribute. The field type must implementFromOptionalXmlText
(forFromXml
) orIntoOptionalXmlText
(forIntoXml
), unless thecodec
option is set.-
name = ..
(default): The XML name of the attribute. If this is not set, the field’s identifier is used. -
namespace = ..
: The XML namespace of the attribute. This is optional, and if absent, only unnamespaced attributes are considered. -
default
,default = ..
: If set, a field value is generated if the attribute is not present andFromOptionalXmlText
did not create a value fromNone
, instead of failing to parse. If the optional argument is present, it must be the path to a callable which returns the field’s type. Otherwise,std::default::Default::default
is used. -
codec = ..
: Path to a type implementingTextCodec
to use instead of theFromOptionalXmlText
/IntoOptionalXmlText
implementation of the field’s type.If set, you need to explicitly add the
default
flag to fields of typeOption<_>
, because the default option logic ofFromOptionalXmlText
is not present.
-
-
child(.., extract(..))
: Extract data from a child element.-
name = ..
(required): The XML name of the child to match. -
namespace = ..
(required): The XML namespace of the child to match. This can be one of the following:- A path referring to a
&'static str
static
which contains the namespace URI of the XML element represented by the struct. super
: Only usable inside compounds with#[xml(namespace = dyn)]
, using#[xml(namespace = super)]
on an extracted field allows to match the field’s child’s namespace with the dynamically determined namespace of the parent (both during serialisation and during deserialisation).
- A path referring to a
-
extract(..)
(required): Specification of data to extract. See below for options. -
skip_if
: If set, this must be the path to a callable. That callable is invoked with a reference to the field’s type at serialisation time. If the callable returns true, the field is omitted from the output completely.This should often be combined with
default
. -
default
,default = ..
: If set, a field value is generated if the child is not present instead of failing to parse. If the optional argument is present, it must be the path to a callable which returns the field’s type. Otherwise,std::default::Default::default
is used.Note: When using
extract(..)
, this is required even when the field’s type isOption<..>
.
-
-
child
,child(..)
(withoutextract(..)
): Extract an entire child element. The field type must implementFromXml
(forFromXml
) orIntoXml
(forIntoXml
).-
namespace = super
: If set, the field must also implementDynNamespace
and the compound the field is in must be set to benamespace = dyn
. In this case, the field’s child is forced to be in the same namespace as the parent during parsing. -
skip_if
: If set, this must be the path to a callable. That callable is invoked with a reference to the field’s type at serialisation time. If the callable returns true, the field is omitted from the output completely.This should often be combined with
default
. -
default
,default = ..
: If set, a field value is generated if the child is not present instead of failing to parse. If the optional argument is present, it must be the path to a callable which returns the field’s type. Otherwise,std::default::Default::default
is used.Note: When using
extract(..)
, this is required even when the field’s type isOption<..>
.
Aside from
namespace = super
, matching of the XML namespace / name is completely delegated to theFromXml
implementation of the field’s type and thus thenamespace
andname
attributes are not allowed. -
-
children(.., extract(..))
: Likechild(.., extract(..))
, with the following differences:-
More than one clause inside
extract(..)
are allowed. -
More than one matching child is allowed
-
The field type must implement
Default
,Extend<T>
andIntoIterator<Item = T>
.T
, must be a tuple type matching the types provided by the extracted parts. -
Extracts must specify their type, because it cannot be inferred through the collection.
-
-
children
,children(..)
(withoutextract(..)
): Extract zero or more entire child elements. The field type must implementDefault
,Extend<T>
andIntoIterator<Item = T>
, whereT
implementsFromXml
(andIntoXml
forIntoXml
).-
skip_if
: If set, this must be the path to a callable. That callable is invoked with a reference to the field’s type at serialisation time. If the callable returns true, the field is omitted from the output completely.This should often be combined with
default
.
The namespace and name to match are determined by the field type, thus it is not allowed to specify them here.
namespace = super
is not supported. -
-
text
,text(..): Extract the element's text contents. The field type must implement
FromXmlText(for [
FromXml]) or
IntoXmlText(for [
IntoXml]), unless the
codec` option is set.codec = ..
: Path to a type implementingTextCodec
to use instead of theFromXmlText
/IntoXmlText
implementation of the field’s type.
-
element
,element(..)
: Collect a single element asminidom::Element
instead of attempting to destructure it. The field type must implementFrom<Element>
andInto<Option<Element>>
(minidom::Element
implements both).name = ..
(optional): The XML name of the element to match.namespace = ..
(optional): The XML namespace of the element to match.default
,default = ..
: If set, a field value is generated if the child is not present instead of failing to parse. If the optional argument is present, it must be the path to a callable which returns the field’s type. Otherwise,std::default::Default::default
is used.
If the field converts into
None
when invokingInto<Option<Element>>
, the element is omitted from the output altogether. -
elements(..)
: Collect otherwise unknown children asminidom::Element
.namespace = ..
: The XML namespace of the element to match.name = ..
(optional): The XML name of the element to match. If omitted, all elements from the given namespace are collected.
-
elements
: Collect all unknown children asminidom::Element
. The field type must beVec<Element>
. -
namespace
: Represent the parent struct/enum variant’s XML namespace. This requires that the compound is declared with#[xml(namespace = dyn)]
. The field type must implementDynNamespaceEnum
. -
ignore
: The field is not considered during parsing or serialisation. The type must implementDefault
.
§Extraction specification
Inside extract(..)
, there must be a list of type annotations as used on
fields. All annotations can be used which can also be used on fields. Because
here there is no possibility to do any inferrence on the field type, the
following field attributes support an additional, optional type
argument:
attribute
text
If the extract(..)
contains exactly one part and the type of the extract
is not specified on that one part, it is assumed to be equal to the type of
the field the extract is used on.
Otherwise, the default is String
, which is not going to work in many cases.
This limitation could be lifted, but we need a use case for it first :). So
if you run into this file an issue please!
Derive macro for FromXml
.