xso 0.4.0

XML Streamed Objects: similar to serde, but XML-native.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
# Make a struct or enum parseable from XML

This derives the [`FromXml`] trait on a struct or enum. It is the counterpart
to [`macro@AsXml`].

## Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo;

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example'/>").unwrap();
assert_eq!(foo, Foo);
```

## Table of contents

1. [Attributes]#attributes
2. [Struct meta]#struct-meta
3. [Enums]#enums
    1. [Name-switched enum meta]#name-switched-enum-meta
    2. [Attribute-switched enum meta]#attribute-switched-enum-meta
    3. [Dynamic enum meta]#dynamic-enum-meta
4. [Field meta]#field-meta
    1. [`attribute` meta]#attribute-meta
    2. [`child` meta]#child-meta
    3. [`element` meta]#element-meta
    4. [`extract` meta]#extract-meta
    5. [`flag` meta]#flag-meta
    6. [`lang` meta]#lang-meta
    6. [`text` meta]#text-meta

## Attributes

The derive macros need additional information, such as XML namespaces and
names to match. This must be specified via key-value pairs on the type or
fields the derive macro is invoked on. These key-value pairs are specified as
Rust attributes. In order to disambiguate between XML attributes and Rust
attributes, we are going to refer to Rust attributes using the term *meta*
instead, which is consistent with the Rust language reference calling that
syntax construct *meta*.

All key-value pairs interpreted by these derive macros must be wrapped in a
`#[xml( ... )]` *meta*.

The values associated with the keys may be of different types, defined as
such:

- *path*: A Rust path, like `some_crate::foo::Bar`. Note that `foo` on its own
  is also a path.
- *string literal*: A string literal, like `"hello world!"`.
- *type*: A Rust type.
- *expression*: A Rust expression.
- *ident*: A single Rust identifier.
- *nested*: The meta is followed by parentheses, inside of which meta-specific
  additional keys are present.
- flag: Has no value. The key's mere presence has relevance and it must not be
  followed by a `=` sign.

## Struct meta

The following keys are defined on structs:

| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | *string literal* or *path* | The XML element namespace to match. If it is a *path*, it must point at a `&'static str`. |
| `name` | *string literal* or *path* | The XML element name to match. If it is a *path*, it must point at a `&'static NcNameStr`. |
| `transparent` | *flag* | If present, declares the struct as *transparent* struct (see below) |
| `builder` | optional *ident* | The name to use for the generated builder type. |
| `iterator` | optional *ident* | The name to use for the generated iterator type. |
| `on_unknown_attribute` | optional *ident* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
| `on_unknown_child` | optional *ident* | Name of an [`UnknownChildPolicy`] member, controlling how unknown children are handled. |
| `discard` | optional *nested* | Contains field specifications of content to ignore. See below for details. |
| `deserialize_callback` | optional *path* | Path to a `fn(&mut T) -> Result<(), Error>` which is called on the deserialized struct after deserialization. |

Note that the `name` value must be a valid XML element name, without colons.
The namespace prefix, if any, is assigned automatically at serialisation time
and cannot be overridden. The following will thus not compile:

```compile_fail
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "fnord:foo")]  // colon not allowed
struct Foo;
```

If `builder` or `iterator` are given, the respective generated types will use
the given names instead of names chosen by the derive macro implementation.
Helper types will use these names as prefix. The exact names of helper types
are implementation defined, which is why any type name starting with the
identifiers passed to either of these keys is considered reserved.

By default, the builder type uses the type's name suffixed with
`FromXmlBuilder` and the iterator type uses the type's name suffixed with
`AsXmlIterator`.

If the struct is marked as `transparent`, it must not have a `namespace` or
`name` set and it must have exactly one field. That field's type must
implement [`FromXml`] in order to derive `FromXml` and [`AsXml`] in order to
derive `AsXml`. The struct will be (de-)serialised exactly like the type of
that single field. This allows a newtype-like pattern for XSO structs.

`discard` may contain zero or more field meta which describe XML content to
silently ignore. The syntax is the same as within the `#[xml(..)]` meta used
on fields, however, any parameters which aren't strictly needed to match the
content are rejected (for example, you cannot set the codec on a discarded
attribute because it is irrelevant). Discarded content is never emitted during
serialisation. Its absence does not cause errors.

```
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo", discard(text))]
struct Foo;
```

## Enums

Two different `enum` flavors are supported:

1. [**Name-switched enums**]#name-switched-enum-meta have a fixed XML
   namespace they match on and each variant corresponds to a different XML
   element name within that namespace.

2. [**Attribute-switched enums**]#attribute-switched-enum-meta have a fixed
   XML element they match which must have a specific attribute. The variants
   correspond to a value of that XML attribute.

3. [**Dynamic enums**]#dynamic-enum-meta have entirely unrelated variants.

At the source-code level, they are distinguished by the meta keys which are
present on the `enum`: The different variants have different sets of mandatory
keys and can thus be uniquely identified.

### Name-switched enum meta

Name-switched enums match a fixed XML namespace and then select the enum
variant based on the XML element's name. Name-switched enums are declared by
setting the `namespace` key on a `enum` item.

The following keys are defined on name-switched enums:

| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | *string literal* or *path* | The XML element namespace to match for this enum. If it is a *path*, it must point at a `&'static str`. |
| `builder` | optional *ident* | The name to use for the generated builder type. |
| `iterator` | optional *ident* | The name to use for the generated iterator type. |
| `exhaustive` | *flag* | If present, the enum considers itself authoritative for its namespace; unknown elements within the namespace are rejected instead of treated as mismatch. |
| `discard` | optional *nested* | Contains field specifications of content to ignore. See the struct meta docs for details. |
| `deserialize_callback` | optional *path* | Path to a `fn(&mut T) -> Result<(), Error>` which is called on the deserialized enum after deserialization. |

All variants of a name-switched enum live within the same namespace and are
distinguished exclusively by their XML name within that namespace. The
contents of the XML element (including attributes) is not inspected before
selecting the variant when parsing XML.

If *exhaustive* is set and an element is encountered which matches the
namespace of the enum, but matches none of its variants, parsing will fail
with an error. If *exhaustive* is *not* set, in such a situation, parsing
would attempt to continue with other siblings of the enum, attempting to find
a handler for that element.

Note that the *exhaustive* flag is orthogonal to the Rust attribute
`#[non_exhaustive]`.

For details on `builder` and `iterator`, see the [Struct meta](#struct-meta)
documentation above.

#### Name-switched enum variant meta

| Key | Value type | Description |
| --- | --- | --- |
| `name` | *string literal* or *path* | The XML element name to match for this variant. If it is a *path*, it must point at a `&'static NcNameStr`. |
| `on_unknown_attribute` | optional *ident* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
| `on_unknown_child` | optional *ident* | Name of an [`UnknownChildPolicy`] member, controlling how unknown children are handled. |

Note that the `name` value must be a valid XML element name, without colons.
The namespace prefix, if any, is assigned automatically at serialisation time
and cannot be overridden.

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example")]
enum Foo {
    #[xml(name = "a")]
    Variant1 {
        #[xml(attribute)]
        foo: String,
    },
    #[xml(name = "b")]
    Variant2 {
        #[xml(attribute)]
        bar: String,
    },
}

let foo: Foo = xso::from_bytes(b"<a xmlns='urn:example' foo='hello'/>").unwrap();
assert_eq!(foo, Foo::Variant1 { foo: "hello".to_string() });

let foo: Foo = xso::from_bytes(b"<b xmlns='urn:example' bar='hello'/>").unwrap();
assert_eq!(foo, Foo::Variant2 { bar: "hello".to_string() });
```

### Attribute-switched enum meta

Attribute-switched enums match a fixed XML element and then select the enum
variant based on a specific attribute on that XML element. Attribute-switched
enums are declared by setting the `namespace`, `name` and `attribute` keys on
a `enum` item.

The following keys are defined on name-switched enums:

| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | *string literal* or *path* | The XML element namespace to match for this enum. If it is a *path*, it must point at a `&'static str`. |
| `name` | *string literal* or *path* | The XML element name to match. If it is a *path*, it must point at a `&'static NcNameStr`. |
| `attribute` | *string literal*, *path* or *nested* | The attribute to match. If it is a *path*, it must point at a `&'static NcNameStr`. |
| `builder` | optional *ident* | The name to use for the generated builder type. |
| `iterator` | optional *ident* | The name to use for the generated iterator type. |
| `exhaustive` | *flag* | Must be set to allow future extensions. |
| `discard` | optional *nested* | Contains field specifications of content to ignore. See the struct meta docs for details. |
| `deserialize_callback` | optional *path* | Path to a `fn(&mut T) -> Result<(), Error>` which is called on the deserialized enum after deserialization. |

`attribute` follows the same syntax and semantic as the
[`attribute` meta](#attribute-meta), but only allows the `namespace` and
`name` keys.

For details on `builder` and `iterator`, see the [Struct meta](#struct-meta)
documentation above.

#### Attribute-switched enum variant meta

| Key | Value type | Description |
| --- | --- | --- |
| `value` | *string literal* | The text content to match for this variant. |
| `on_unknown_attribute` | optional *ident* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
| `on_unknown_child` | optional *ident* | Name of an [`UnknownChildPolicy`] member, controlling how unknown children are handled. |

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo", attribute = "version", exhaustive)]
enum Foo {
    #[xml(value = "a")]
    Variant1 {
        #[xml(attribute)]
        foo: String,
    },
    #[xml(value = "b")]
    Variant2 {
        #[xml(attribute)]
        bar: String,
    },
}

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example' version='a' foo='hello'/>").unwrap();
assert_eq!(foo, Foo::Variant1 { foo: "hello".to_string() });

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example' version='b' bar='hello'/>").unwrap();
assert_eq!(foo, Foo::Variant2 { bar: "hello".to_string() });
```

### Dynamic enum meta

Dynamic enums select their variants by attempting to match them in declaration
order. Dynamic enums are declared by not setting the `namespace` key on an
`enum` item.

The following keys are defined on dynamic enums:

| Key | Value type | Description |
| --- | --- | --- |
| `builder` | optional *ident* | The name to use for the generated builder type. |
| `iterator` | optional *ident* | The name to use for the generated iterator type. |
| `discard` | optional *nested* | Contains field specifications of content to ignore. See the struct meta docs for details. |
| `deserialize_callback` | optional *path* | Path to a `fn(&mut T) -> Result<(), Error>` which is called on the deserialized enum after deserialization. |

For details on `builder` and `iterator`, see the [Struct meta](#struct-meta)
documentation above.

#### Dynamic enum variant meta

Dynamic enum variants are completely independent of one another and thus use
the same meta structure as structs. See [Struct meta](#struct-meta) for
details.

The `builder`, `iterator` and `debug` keys cannot be used on dynamic enum
variants.

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml()]
enum Foo {
    #[xml(namespace = "urn:example:ns1", name = "a")]
    Variant1 {
        #[xml(attribute)]
        foo: String,
    },
    #[xml(namespace = "urn:example:ns2", name = "b")]
    Variant2 {
        #[xml(attribute)]
        bar: String,
    },
}

let foo: Foo = xso::from_bytes(b"<a xmlns='urn:example:ns1' foo='hello'/>").unwrap();
assert_eq!(foo, Foo::Variant1 { foo: "hello".to_string() });

let foo: Foo = xso::from_bytes(b"<b xmlns='urn:example:ns2' bar='hello'/>").unwrap();
assert_eq!(foo, Foo::Variant2 { bar: "hello".to_string() });
```

## Field meta

For fields, the *meta* consists of a nested meta inside the `#[xml(..)]` meta,
the identifier of which controls *how* the field is mapped to XML, while the
contents control the parameters of that mapping.

The following mapping types are defined:

| Type | Description |
| --- | --- |
| [`attribute`]#attribute-meta | Map the field to an XML attribute on the struct's element |
| [`child`]#child-meta | Map the field to a child element |
| [`element`]#element-meta | Map the field to a child element as [`minidom::Element`] |
| [`extract`]#extract-meta | Map the field to contents of a child element of specified structure |
| [`text`]#text-meta | Map the field to the text content of the struct's element |

#### 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(element(n = ..))]`, 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 `AsXml` 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.

### `attribute` meta

The `attribute` meta causes the field to be mapped to an XML attribute of the
same name. For `FromXml`, the field's type must implement [`FromXmlText`] and
for `AsXml`, the field's type must implement [`AsOptionalXmlText`].

The following keys can be used inside the `#[xml(attribute(..))]` meta:

| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | optional *string literal* or *path* | The namespace of the XML attribute to match. If it is a *path*, it must point at a `&'static str`. Note that attributes, unlike elements, are unnamespaced by default. |
| `name` | optional *string literal* or *path* | The name of the XML attribute to match. If it is a *path*, it must point at a `&'static NcNameStr`. |
| `default` | *flag* | If present, an absent attribute will substitute the default value instead of raising an error. |
| `type_` | *type* | Optional explicit type specification. Only allowed within `#[xml(extract(fields(..)))]`. |
| `codec` | optional *expression* | [`TextCodec`] implementation which is used to encode or decode the field. |

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
expanded to the corresponding namespace URI and the value for the `namespace`
key is implied. Mixing a prefixed name with an explicit `namespace` key is
not allowed.

The `attribute` meta also supports a shorthand syntax,
`#[xml(attribute = ..)]`, where the value is treated as the value for the
`name` key (with optional prefix as described above, and unnamespaced
otherwise).

If `default` is specified and the attribute is absent in the source, the value
is generated using [`core::default::Default`], requiring the field type to
implement the `Default` trait for a `FromXml` derivation. `default` has no
influence on `AsXml`.

If `type_` is specified and the `attribute` meta is used within an
`#[xml(extract(fields(..)))]` meta, the specified type is used instead of the
field type on which the `extract` is declared.

If `codec` is given, the given `codec` value must implement
[`TextCodec<T>`][`TextCodec`] where `T` is the type of the field.

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo {
    #[xml(attribute)]
    a: String,
    #[xml(attribute = "bar")]
    b: String,
    #[xml(attribute(name = "baz"))]
    c: String,
    #[xml(attribute(namespace = "urn:example", name = "fnord"))]
    d: String,
    #[xml(attribute = "xml:lang")]
    e: String,
};

let foo: Foo = xso::from_bytes(b"<foo
    xmlns='urn:example'
    a='1' bar='2' baz='3'
    xmlns:tns0='urn:example' tns0:fnord='4'
    xml:lang='5'
/>").unwrap();
assert_eq!(foo, Foo {
    a: "1".to_string(),
    b: "2".to_string(),
    c: "3".to_string(),
    d: "4".to_string(),
    e: "5".to_string(),
});
```

Note that it is not possible to have two `#[xml(attribute)]` fields which
match the same XML attribute:

```compile_fail
# use xso::FromXml;
#[derive(FromXml)]
#[xml(namespace = "urn:example", name = "dup")]
struct Dup {
    #[xml(attribute)]
    a: String,

    #[xml(attribute = "a")]
    b: String,
}
```

```compile_fail
# use xso::FromXml;
static A: &str = "a";

#[derive(FromXml)]
#[xml(namespace = "urn:example", name = "dup")]
struct Dup {
    #[xml(attribute)]
    a: String,

    #[xml(attribute = A)]
    b: String,
}
```

### `child` meta

The `child` meta causes the field to be mapped to a child element of the
element.

The following keys can be used inside the `#[xml(child(..))]` meta:

| Key | Value type | Description |
| --- | --- | --- |
| `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`. |

When parsing a single child element (i.e. `n = 1` or no `n` value set at all),
the field's type must implement [`FromXml`] in order to derive `FromXml` and
[`AsXml`] in order to derive `AsXml`.

When parsing a collection (with `n = ..`), the field's type must implement
[`IntoIterator<Item = T>`][`core::iter::IntoIterator`], where `T` must
implement [`FromXml`] in order to derive `FromXml` and [`AsXml`] in order to
derive `AsXml`. In addition, the field's type must implement
[`Extend<T>`][`core::iter::Extend`] to derive `FromXml` and the field's
reference type must implement `IntoIterator<Item = &'_ T>` to derive `AsXml`.

If `default` is specified and the child is absent in the source, the value
is generated using [`core::default::Default`], requiring the field type to
implement the `Default` trait for a `FromXml` derivation. `default` has no
influence on `AsXml`. Combining `default` and `n` where `n` is not set to `1`
is not supported and will cause a compile-time error.

Using `default` with a type other than `Option<T>` will cause the
serialisation to mismatch the deserialisation (i.e. the struct is then not
roundtrip-safe), because the deserialisation does not compare the value
against `default` (but has special provisions to work with `Option<T>`).

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "child")]
struct Child {
    #[xml(attribute = "some-attr")]
    some_attr: String,
}

#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "other-child")]
struct OtherChild {
    #[xml(attribute = "some-attr")]
    some_attr: String,
}

#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "parent")]
struct Parent {
    #[xml(attribute)]
    foo: String,

    #[xml(child)]
    bar: Child,

    #[xml(child(n = ..))]
    baz: Vec<OtherChild>,
}

let parent: Parent = xso::from_bytes(b"<parent
    xmlns='urn:example'
    foo='hello world!'
><child
    some-attr='within'
/><other-child
    some-attr='c1'
/><other-child
    some-attr='c2'
/></parent>").unwrap();
assert_eq!(parent, Parent {
    foo: "hello world!".to_owned(),
    bar: Child { some_attr: "within".to_owned() },
    baz: vec! [
        OtherChild { some_attr: "c1".to_owned() },
        OtherChild { some_attr: "c2".to_owned() },
    ],
});
```

### `element` meta

The `element` meta causes the field to be mapped to child elements, stored as
a container containing [`minidom::Element`] instances.

This meta is only available if `xso` is being built with the `"minidom"`
feature.

The following keys can be used inside the `#[xml(extract(..))]` meta:

| Key | Value type | Description |
| --- | --- | --- |
| `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`. |

When parsing a single child element (i.e. `n = 1` or no `n` value set at all),
the field's type must be a `minidom::Element`.

When parsing a collection (with `n = ..`), the field's type must be a
collection of `minidom::Element`. It must thus implement
[`IntoIterator<Item = minidom::Element>`][`core::iter::IntoIterator`]. In
addition, the field's type must implement
[`Extend<minidom::Element>`][`core::iter::Extend`] to derive `FromXml` and the
field's reference type must implement
`IntoIterator<Item = &'_ minidom::Element>` to derive `AsXml`.

If `default` is specified and the child is absent in the source, the value
is generated using [`core::default::Default`]. `default` has no influence on
`AsXml`. Combining `default` and `n` where `n` is not set to `1` is not
supported and will cause a compile-time error.

Using `default` with a type other than `Option<T>` will cause the
serialisation to mismatch the deserialisation (i.e. the struct is then not
roundtrip-safe), because the deserialisation does not compare the value
against `default` (but has special provisions to work with `Option<T>`).

Fields with the `element` meta are deserialised with the lowest priority.
While other fields are processed in the order they are declared, `element`
fields may capture arbitrary child elements, so they are considered as the
last choice when no other field matched a given child element. In addition,
it is not allowed to have more than one field in any given struct with the
`#[xml(element)]` meta.

#### Example

```rust
# #[cfg(feature = "minidom")]
# {
# use xso::FromXml;
# use xso::exports::minidom;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "parent")]
struct Parent {
    #[xml(element(n = ..))]
    misc: Vec<minidom::Element>,
}

let parent: Parent = xso::from_bytes(b"<parent
    xmlns='urn:example'
><child-a/><child-b/><child-a/></parent>").unwrap();
assert_eq!(parent.misc[0].name(), "child-a");
assert_eq!(parent.misc[1].name(), "child-b");
assert_eq!(parent.misc[2].name(), "child-a");
# }
```

### `extract` meta

The `extract` meta causes the field to be mapped to the *contents* of a child
element.

The following keys can be used inside the `#[xml(extract(..))]` meta:

| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | optional *string literal* or *path* | The XML namespace of the child element. |
| `name` | optional *string literal* or *path* | The XML name of the child element. If it is a *path*, it must point at a `&'static NcNameStr`. |
| `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` | optional *ident* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
| `on_unknown_child` | optional *ident* | 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
expanded to the corresponding namespace URI and the value for the `namespace`
key is implied. Mixing a prefixed name with an explicit `namespace` key is
not allowed.

Both `namespace` and `name` may be omitted. If `namespace` is omitted, it
defaults to the namespace of the surrounding container. If `name` is omitted
and the `extract` meta is being used on a named field, that field's name is
used. If `name` is omitted and `extract` is not used on a named field, an
error is emitted.

When parsing a single child element (i.e. `n = 1` or no `n` value set at all),
the extracted field's type is set to be the same type as the field on which
the extract is declared, unless overridden in the extracted field's meta.

When parsing a collection (with `n = ..`), the extracted fields within
`fields()` must all have type specifications. Not all fields kinds support
that.

The sequence of field meta inside `fields` can be thought of as a nameless
tuple-style struct. The macro generates serialisation/deserialisation code
for that nameless tuple-style struct and uses it to serialise/deserialise
the field.

If `default` is specified and the child is absent in the source, the value
is generated using [`core::default::Default`], requiring the field type to
implement the `Default` trait for a `FromXml` derivation. `default` has no
influence on `AsXml`. Combining `default` and `n` where `n` is not set to `1`
is not supported and will cause a compile-time error.

Mixing `default` on the `#[xml(extract)]` itself with `default` on the
extracted inner fields creates non-roundtrip-safe parsing, unless you also
use twice-nested [`core::option::Option`] types. That means that when
deserialising a piece of XML and reserialising it without changing the
contents of the struct in Rust, the resulting XML may not match the input.
This is because to the serialiser, if only one layer of
[`core::option::Option`] is used, it is not possible to distinguish which of
the two layers were defaulted. The exact behaviour on serialisation in such a
situation is *not guaranteed* and may change between versions of the `xso`
crate, its dependencies, the standard library, or even rustc itself.

Using `default` with a type other than `Option<T>` will cause the
serialisation to mismatch the deserialisation, too (i.e. the struct is then
not roundtrip-safe), because the deserialisation does not compare the value
against `default` (but has special provisions to work with `Option<T>`).

If more than one single field is contained in `fields`, the fields will be
extracted as a tuple in the order they are given in the meta. In addition, it
is required to explicitly specify each extracted field's type in that case.

Using `extract` instead of `child` combined with a specific struct declaration
comes with trade-offs. On the one hand, using `extract` gives you flexibility
in regard of the specific serialisation of a field: it is possible to exchange
a nested child element for an attribute without changing the Rust interface
of the struct.

On the other hand, `extract` meta declarations can quickly become unwieldy
and they may not support all configuration options which may in the future be
added on structs (such as configuring handling of undeclared attributes) and
they cannot be used for enumerations.

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo {
    #[xml(extract(namespace = "urn:example", name = "bar", fields(attribute = "a")))]
    a: String,
}

let foo: Foo = xso::from_bytes(b"<foo
    xmlns='urn:example'><bar a='xyz'/></foo>").unwrap();
assert_eq!(foo, Foo {
    a: "xyz".to_string(),
});
```

### `flag` meta

The `flag` meta causes the field to be mapped to a single, optional child element. Absence of the child is equivalent to the value `false`, presence
of the child element is equivalent to the value `true`.

The following keys can be used inside the `#[xml(flag(..))]` meta:

| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | optional *string literal* or *path* | The namespace of the XML element to match. If it is a *path*, it must point at a `&'static str`. |
| `name` | optional *string literal* or *path* | The name of the XML element to match. If it is a *path*, it must point at a `&'static NcNameStr`. |

The field on which the `flag` meta is used must be of type `bool`.

Both `namespace` and `name` may be omitted. If `namespace` is omitted, it
defaults to the namespace of the surrounding container. If `name` is omitted
and the `flag` meta is being used on a named field, that field's name is
used. If `name` is omitted and `flag` is not used on a named field, an
error is emitted.

When parsing, any contents within the child element generate a parse error.

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo {
    #[xml(flag(name = "flag"))]
    flag: bool,
};

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example'><flag/></foo>").unwrap();
assert_eq!(foo, Foo {
    flag: true,
});

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example'/>").unwrap();
assert_eq!(foo, Foo {
    flag: false,
});
```

### `lang` meta

The `lang` meta allows to access the (potentially inherited) logical
`xml:lang` value as defined in
[XML 1.0 ยง 2.12](https://www.w3.org/TR/REC-xml/#sec-lang-tag). For `FromXml`,
the field's type must implement [`FromXmlText`] and for `AsXml`, the field's
type must implement [`AsOptionalXmlText`].

| Key | Value type | Description |
| --- | --- | --- |
| `default` | *flag* | If present, an absent attribute will substitute the default value instead of raising an error. |
| `type_` | *type* | Optional explicit type specification. Only allowed within `#[xml(extract(fields(..)))]`. |
| `codec` | optional *expression* | [`TextCodec`] implementation which is used to encode or decode the field. |

Unlike `#[xml(attribute = "xml:lang")]`, using `#[xml(lang)]` takes
the inheritance of the `xml:lang` attribute into account.

**Note:** Using this meta is not roundtrip-safe. `xso` will always emit its
value on serialisation, even if it was inherited during deserialisation.

If `default` is specified and there is no `xml:lang` specified at the point of
the element, the value is generated using [`core::default::Default`],
requiring the field type to implement the `Default` trait for a `FromXml`
derivation. `default` has no influence on `AsXml`. If `default` is not
specified, an error is raised if `xml:lang` has not been set on the element
or any of its ancestors.

Note that no error is generated (by `xso`) for `xml:lang` values of `""`.

If `type_` is specified and the `lang` meta is used within an
`#[xml(extract(fields(..)))]` meta, the specified type is used instead of the
field type on which the `extract` is declared.

If `codec` is given, the given `codec` value must implement
[`TextCodec<T>`][`TextCodec`] where `T` is the type of the field.

#### Example

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "bar")]
struct Bar {
    #[xml(lang)]
    lang: Option<String>,
};

#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo {
    #[xml(child)]
    child: Bar,
};

// `xml:lang` gets inherited from <foo/> to <bar/>
let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example' xml:lang='en'><bar/></foo>").unwrap();
assert_eq!(foo, Foo {
    child: Bar {
        lang: Some("en".to_owned()),
    },
});

// `xml:lang` gets set/overwritten in <bar/>
let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example' xml:lang='en'><bar xml:lang='de'/></foo>").unwrap();
assert_eq!(foo, Foo {
    child: Bar {
        lang: Some("de".to_owned()),
    },
});
```

Note that it is not possible to use `#[xml(lang)]` and an `#[xml(attribute)]`
which also matches `xml:lang` in the same struct:

```compile_fail
# use xso::FromXml;
# use xso::exports::rxml::XMLNS_XML;
#[derive(FromXml)]
#[xml(namespace = "urn:example", name = "dup")]
struct Dup {
    #[xml(attribute(namespace = XMLNS_XML, name = "lang"))]
    a: String,

    #[xml(lang)]
    b: Option<String>,
}
```

### `text` meta

The `text` meta causes the field to be mapped to the text content of the
element.

| Key | Value type | Description |
| --- | --- | --- |
| `codec` | optional *expression* | [`TextCodec`] implementation which is used to encode or decode the field. |
| `type_` | optional *type* | Explicit type specification. Only allowed within `#[xml(extract(fields(..)))]`. |

If `codec` is given, the given `codec` value must implement
[`TextCodec<T>`][`TextCodec`] where `T` is the type of the field.

If `codec` is *not* given, the field's type must implement [`FromXmlText`] for
`FromXml` and for `AsXml`, the field's type must implement [`AsXmlText`].

If `type_` is specified and the `text` meta is used within an
`#[xml(extract(fields(..)))]` meta, the specified type is used instead of the
field type on which the `extract` is declared.

The `text` meta also supports a shorthand syntax, `#[xml(text = ..)]`, where
the value is treated as the value for the `codec` key (with optional prefix as
described above, and unnamespaced otherwise).

Only a single field per struct may be annotated with `#[xml(text)]` at a time,
to avoid parsing ambiguities. This is also true if only `AsXml` is derived on
a field, for consistency.

#### Example without codec

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo {
    #[xml(text)]
    a: String,
};

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example'>hello</foo>").unwrap();
assert_eq!(foo, Foo {
    a: "hello".to_string(),
});
```

#### Example with codec

```rust
# use xso::FromXml;
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = "urn:example", name = "foo")]
struct Foo {
    #[xml(text = xso::text::EmptyAsNone)]
    a: Option<String>,
};

let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example'/>").unwrap();
assert_eq!(foo, Foo {
    a: None,
});
```