1// Copyright (c) 2017-2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7macro_rules! get_attr {
8 ($elem:ident, $attr:tt, $type:tt) => (
9 get_attr!($elem, $attr, $type, value, value.parse()?)
10 );
11 ($elem:ident, $attr:tt, optional_empty, $value:ident, $func:expr) => (
12 match $elem.attr($attr) {
13 Some("") => None,
14 Some($value) => Some($func),
15 None => None,
16 }
17 );
18 ($elem:ident, $attr:tt, optional, $value:ident, $func:expr) => (
19 match $elem.attr($attr) {
20 Some($value) => Some($func),
21 None => None,
22 }
23 );
24 ($elem:ident, $attr:tt, required, $value:ident, $func:expr) => (
25 match $elem.attr($attr) {
26 Some($value) => $func,
27 None => return Err(::error::Error::ParseError(concat!("Required attribute '", $attr, "' missing."))),
28 }
29 );
30 ($elem:ident, $attr:tt, default, $value:ident, $func:expr) => (
31 match $elem.attr($attr) {
32 Some($value) => $func,
33 None => ::std::default::Default::default(),
34 }
35 );
36}
37
38macro_rules! generate_attribute {
39 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+,}) => (
40 generate_attribute!($(#[$meta])* $elem, $name, {$($(#[$a_meta])* $a => $b),+});
41 );
42 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+,}, Default = $default:ident) => (
43 generate_attribute!($(#[$meta])* $elem, $name, {$($(#[$a_meta])* $a => $b),+}, Default = $default);
44 );
45 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+}) => (
46 $(#[$meta])*
47 #[derive(Debug, Clone, PartialEq)]
48 pub enum $elem {
49 $(
50 $(#[$a_meta])*
51 $a
52 ),+
53 }
54 impl ::std::str::FromStr for $elem {
55 type Err = ::error::Error;
56 fn from_str(s: &str) -> Result<$elem, ::error::Error> {
57 Ok(match s {
58 $($b => $elem::$a),+,
59 _ => return Err(::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
60 })
61 }
62 }
63 impl ::minidom::IntoAttributeValue for $elem {
64 fn into_attribute_value(self) -> Option<String> {
65 Some(String::from(match self {
66 $($elem::$a => $b),+
67 }))
68 }
69 }
70 );
71 ($(#[$meta:meta])* $elem:ident, $name:tt, {$($(#[$a_meta:meta])* $a:ident => $b:tt),+}, Default = $default:ident) => (
72 $(#[$meta])*
73 #[derive(Debug, Clone, PartialEq)]
74 pub enum $elem {
75 $(
76 $(#[$a_meta])*
77 $a
78 ),+
79 }
80 impl ::std::str::FromStr for $elem {
81 type Err = ::error::Error;
82 fn from_str(s: &str) -> Result<$elem, ::error::Error> {
83 Ok(match s {
84 $($b => $elem::$a),+,
85 _ => return Err(::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
86 })
87 }
88 }
89 impl ::minidom::IntoAttributeValue for $elem {
90 #[allow(unreachable_patterns)]
91 fn into_attribute_value(self) -> Option<String> {
92 Some(String::from(match self {
93 $elem::$default => return None,
94 $($elem::$a => $b),+
95 }))
96 }
97 }
98 impl ::std::default::Default for $elem {
99 fn default() -> $elem {
100 $elem::$default
101 }
102 }
103 );
104 ($(#[$meta:meta])* $elem:ident, $name:tt, bool) => (
105 $(#[$meta])*
106 #[derive(Debug, Clone, PartialEq)]
107 pub enum $elem {
108 /// True value, represented by either 'true' or '1'.
109 True,
110 /// False value, represented by either 'false' or '0'.
111 False,
112 }
113 impl ::std::str::FromStr for $elem {
114 type Err = ::error::Error;
115 fn from_str(s: &str) -> Result<Self, ::error::Error> {
116 Ok(match s {
117 "true" | "1" => $elem::True,
118 "false" | "0" => $elem::False,
119 _ => return Err(::error::Error::ParseError(concat!("Unknown value for '", $name, "' attribute."))),
120 })
121 }
122 }
123 impl ::minidom::IntoAttributeValue for $elem {
124 fn into_attribute_value(self) -> Option<String> {
125 match self {
126 $elem::True => Some(String::from("true")),
127 $elem::False => None
128 }
129 }
130 }
131 impl ::std::default::Default for $elem {
132 fn default() -> $elem {
133 $elem::False
134 }
135 }
136 );
137}
138
139macro_rules! generate_element_enum {
140 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
141 generate_element_enum!($(#[$meta])* $elem, $name, $ns, {$($(#[$enum_meta])* $enum => $enum_name),+});
142 );
143 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+}) => (
144 $(#[$meta])*
145 #[derive(Debug, Clone, PartialEq)]
146 pub enum $elem {
147 $(
148 $(#[$enum_meta])*
149 $enum
150 ),+
151 }
152 impl ::try_from::TryFrom<::minidom::Element> for $elem {
153 type Err = ::error::Error;
154 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
155 check_ns_only!(elem, $name, $ns);
156 check_no_children!(elem, $name);
157 check_no_attributes!(elem, $name);
158 Ok(match elem.name() {
159 $($enum_name => $elem::$enum,)+
160 _ => return Err(::error::Error::ParseError(concat!("This is not a ", $name, " element."))),
161 })
162 }
163 }
164 impl From<$elem> for ::minidom::Element {
165 fn from(elem: $elem) -> ::minidom::Element {
166 ::minidom::Element::builder(match elem {
167 $($elem::$enum => $enum_name,)+
168 }).ns(::ns::$ns)
169 .build()
170 }
171 }
172 );
173}
174
175macro_rules! generate_attribute_enum {
176 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+,}) => (
177 generate_attribute_enum!($(#[$meta])* $elem, $name, $ns, $attr, {$($(#[$enum_meta])* $enum => $enum_name),+});
178 );
179 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $attr:tt, {$($(#[$enum_meta:meta])* $enum:ident => $enum_name:tt),+}) => (
180 $(#[$meta])*
181 #[derive(Debug, Clone, PartialEq)]
182 pub enum $elem {
183 $(
184 $(#[$enum_meta])*
185 $enum
186 ),+
187 }
188 impl ::try_from::TryFrom<::minidom::Element> for $elem {
189 type Err = ::error::Error;
190 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
191 check_ns_only!(elem, $name, $ns);
192 check_no_children!(elem, $name);
193 check_no_unknown_attributes!(elem, $name, [$attr]);
194 Ok(match get_attr!(elem, $attr, required) {
195 $($enum_name => $elem::$enum,)+
196 _ => return Err(::error::Error::ParseError(concat!("Invalid ", $name, " ", $attr, " value."))),
197 })
198 }
199 }
200 impl From<$elem> for ::minidom::Element {
201 fn from(elem: $elem) -> ::minidom::Element {
202 ::minidom::Element::builder($name)
203 .ns(::ns::$ns)
204 .attr($attr, match elem {
205 $($elem::$enum => $enum_name,)+
206 })
207 .build()
208 }
209 }
210 );
211}
212
213macro_rules! check_self {
214 ($elem:ident, $name:tt, $ns:ident) => (
215 check_self!($elem, $name, $ns, $name);
216 );
217 ($elem:ident, $name:tt, $ns:ident, $pretty_name:tt) => (
218 if !$elem.is($name, ::ns::$ns) {
219 return Err(::error::Error::ParseError(concat!("This is not a ", $pretty_name, " element.")));
220 }
221 );
222}
223
224macro_rules! check_ns_only {
225 ($elem:ident, $name:tt, $ns:ident) => (
226 if !$elem.has_ns(::ns::$ns) {
227 return Err(::error::Error::ParseError(concat!("This is not a ", $name, " element.")));
228 }
229 );
230}
231
232macro_rules! check_no_children {
233 ($elem:ident, $name:tt) => (
234 for _ in $elem.children() {
235 return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
236 }
237 );
238}
239
240macro_rules! check_no_attributes {
241 ($elem:ident, $name:tt) => (
242 for _ in $elem.attrs() {
243 return Err(::error::Error::ParseError(concat!("Unknown attribute in ", $name, " element.")));
244 }
245 );
246}
247
248macro_rules! check_no_unknown_attributes {
249 ($elem:ident, $name:tt, [$($attr:tt),*]) => (
250 for (_attr, _) in $elem.attrs() {
251 $(
252 if _attr == $attr {
253 continue;
254 }
255 )*
256 return Err(::error::Error::ParseError(concat!("Unknown attribute in ", $name, " element.")));
257 }
258 );
259}
260
261macro_rules! generate_empty_element {
262 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident) => (
263 $(#[$meta])*
264 #[derive(Debug, Clone)]
265 pub struct $elem;
266
267 impl ::try_from::TryFrom<::minidom::Element> for $elem {
268 type Err = ::error::Error;
269
270 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
271 check_self!(elem, $name, $ns);
272 check_no_children!(elem, $name);
273 check_no_attributes!(elem, $name);
274 Ok($elem)
275 }
276 }
277
278 impl From<$elem> for ::minidom::Element {
279 fn from(_: $elem) -> ::minidom::Element {
280 ::minidom::Element::builder($name)
281 .ns(::ns::$ns)
282 .build()
283 }
284 }
285 );
286}
287
288macro_rules! generate_element_with_only_attributes {
289 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),+,]) => (
290 generate_element_with_only_attributes!($(#[$meta])* $elem, $name, $ns, [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*]);
291 );
292 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),+]) => (
293 $(#[$meta])*
294 #[derive(Debug, Clone)]
295 pub struct $elem {
296 $(
297 $(#[$attr_meta])*
298 pub $attr: $attr_type,
299 )*
300 }
301
302 impl ::try_from::TryFrom<::minidom::Element> for $elem {
303 type Err = ::error::Error;
304
305 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
306 check_self!(elem, $name, $ns);
307 check_no_children!(elem, $name);
308 check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
309 Ok($elem {
310 $(
311 $attr: get_attr!(elem, $attr_name, $attr_action),
312 )*
313 })
314 }
315 }
316
317 impl From<$elem> for ::minidom::Element {
318 fn from(elem: $elem) -> ::minidom::Element {
319 ::minidom::Element::builder($name)
320 .ns(::ns::$ns)
321 $(
322 .attr($attr_name, elem.$attr)
323 )*
324 .build()
325 }
326 }
327 );
328}
329
330macro_rules! generate_id {
331 ($elem:ident) => (
332 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
333 pub struct $elem(pub String);
334 impl ::std::str::FromStr for $elem {
335 type Err = ::error::Error;
336 fn from_str(s: &str) -> Result<$elem, ::error::Error> {
337 // TODO: add a way to parse that differently when needed.
338 Ok($elem(String::from(s)))
339 }
340 }
341 impl ::minidom::IntoAttributeValue for $elem {
342 fn into_attribute_value(self) -> Option<String> {
343 Some(self.0)
344 }
345 }
346 );
347}
348
349macro_rules! generate_elem_id {
350 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident) => (
351 $(#[$meta])*
352 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
353 pub struct $elem(pub String);
354 impl ::std::str::FromStr for $elem {
355 type Err = ::error::Error;
356 fn from_str(s: &str) -> Result<$elem, ::error::Error> {
357 // TODO: add a way to parse that differently when needed.
358 Ok($elem(String::from(s)))
359 }
360 }
361 impl ::try_from::TryFrom<::minidom::Element> for $elem {
362 type Err = ::error::Error;
363 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
364 check_self!(elem, $name, $ns);
365 check_no_children!(elem, $name);
366 check_no_attributes!(elem, $name);
367 // TODO: add a way to parse that differently when needed.
368 Ok($elem(elem.text()))
369 }
370 }
371 impl From<$elem> for ::minidom::Element {
372 fn from(elem: $elem) -> ::minidom::Element {
373 ::minidom::Element::builder($name)
374 .ns(::ns::$ns)
375 .append(elem.0)
376 .build()
377 }
378 }
379 );
380}
381
382macro_rules! generate_element_with_text {
383 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, $text_ident:ident: $codec:ident < $text_type:ty >) => (
384 generate_element_with_text!($(#[$meta])* $elem, $name, $ns, [], $text_ident: $codec<$text_type>);
385 );
386 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], $text_ident:ident: $codec:ident < $text_type:ty >) => (
387 $(#[$meta])*
388 #[derive(Debug, Clone)]
389 pub struct $elem {
390 $(
391 $(#[$attr_meta])*
392 pub $attr: $attr_type,
393 )*
394 pub $text_ident: $text_type,
395 }
396
397 impl ::try_from::TryFrom<::minidom::Element> for $elem {
398 type Err = ::error::Error;
399
400 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
401 check_self!(elem, $name, $ns);
402 check_no_children!(elem, $name);
403 check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
404 Ok($elem {
405 $(
406 $attr: get_attr!(elem, $attr_name, $attr_action),
407 )*
408 $text_ident: $codec::decode(&elem.text())?,
409 })
410 }
411 }
412
413 impl From<$elem> for ::minidom::Element {
414 fn from(elem: $elem) -> ::minidom::Element {
415 ::minidom::Element::builder($name)
416 .ns(::ns::$ns)
417 $(
418 .attr($attr_name, elem.$attr)
419 )*
420 .append($codec::encode(&elem.$text_ident))
421 .build()
422 }
423 }
424 );
425}
426
427macro_rules! generate_element_with_children {
428 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
429 generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], children: [$($(#[$child_meta])* $child_ident: Vec<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
430 );
431 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
432 generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], children: [$($(#[$child_meta])* $child_ident: Vec<$child_type> = ($child_name, $child_ns) => $child_constructor),+]);
433 );
434 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], children: [$($(#[$child_meta:meta])* $child_ident:ident: Vec<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident),+]) => (
435 $(#[$meta])*
436 #[derive(Debug, Clone)]
437 pub struct $elem {
438 $(
439 $(#[$attr_meta])*
440 pub $attr: $attr_type,
441 )*
442 $(
443 $(#[$child_meta])*
444 pub $child_ident: Vec<$child_type>,
445 )*
446 }
447
448 impl ::try_from::TryFrom<::minidom::Element> for $elem {
449 type Err = ::error::Error;
450
451 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
452 check_self!(elem, $name, $ns);
453 check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
454 let mut parsed_children = vec!();
455 for child in elem.children() {
456 $(
457 if child.is($child_name, ::ns::$child_ns) {
458 let parsed_child = $child_constructor::try_from(child.clone())?;
459 parsed_children.push(parsed_child);
460 continue;
461 }
462 )*
463 return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
464 }
465 Ok($elem {
466 $(
467 $attr: get_attr!(elem, $attr_name, $attr_action),
468 )*
469 $(
470 $child_ident: parsed_children,
471 )*
472 })
473 }
474 }
475
476 impl From<$elem> for ::minidom::Element {
477 fn from(elem: $elem) -> ::minidom::Element {
478 ::minidom::Element::builder($name)
479 .ns(::ns::$ns)
480 $(
481 .attr($attr_name, elem.$attr)
482 )*
483 $(
484 .append(elem.$child_ident)
485 )*
486 .build()
487 }
488 }
489 );
490 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
491 generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], child: ($(#[$child_meta])* $child_ident: Option<$child_type> = ($child_name, $child_ns) => $child_constructor));
492 );
493 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
494 generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], child: ($(#[$child_meta])* $child_ident: Option<$child_type> = ($child_name, $child_ns) => $child_constructor));
495 );
496 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], child: ($(#[$child_meta:meta])* $child_ident:ident: Option<$child_type:ty> = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
497 $(#[$meta])*
498 #[derive(Debug, Clone)]
499 pub struct $elem {
500 $(
501 $(#[$attr_meta])*
502 pub $attr: $attr_type,
503 )*
504 $(#[$child_meta])*
505 pub $child_ident: Option<$child_type>,
506 }
507
508 impl ::try_from::TryFrom<::minidom::Element> for $elem {
509 type Err = ::error::Error;
510
511 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
512 check_self!(elem, $name, $ns);
513 check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
514 let mut parsed_child = None;
515 for child in elem.children() {
516 if child.is($child_name, ::ns::$child_ns) {
517 parsed_child = Some($child_constructor::try_from(child.clone())?);
518 continue;
519 }
520 return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
521 }
522 Ok($elem {
523 $(
524 $attr: get_attr!(elem, $attr_name, $attr_action),
525 )*
526 $child_ident: parsed_child,
527 })
528 }
529 }
530
531 impl From<$elem> for ::minidom::Element {
532 fn from(elem: $elem) -> ::minidom::Element {
533 ::minidom::Element::builder($name)
534 .ns(::ns::$ns)
535 $(
536 .attr($attr_name, elem.$attr)
537 )*
538 .append(elem.$child_ident)
539 .build()
540 }
541 }
542 );
543 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
544 generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [], child: ($(#[$child_meta])* $child_ident: $child_type = ($child_name, $child_ns) => $child_constructor));
545 );
546 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*,], child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
547 generate_element_with_children!($(#[$meta])* $elem, $name, $ns, attributes: [$($(#[$attr_meta])* $attr: $attr_type = $attr_name => $attr_action),*], child: ($(#[$child_meta])* $child_ident: $child_type = ($child_name, $child_ns) => $child_constructor));
548 );
549 ($(#[$meta:meta])* $elem:ident, $name:tt, $ns:ident, attributes: [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),*], child: ($(#[$child_meta:meta])* $child_ident:ident: $child_type:ty = ($child_name:tt, $child_ns:ident) => $child_constructor:ident)) => (
550 $(#[$meta])*
551 #[derive(Debug, Clone)]
552 pub struct $elem {
553 $(
554 $(#[$attr_meta])*
555 pub $attr: $attr_type,
556 )*
557 $(#[$child_meta])*
558 pub $child_ident: $child_type,
559 }
560
561 impl ::try_from::TryFrom<::minidom::Element> for $elem {
562 type Err = ::error::Error;
563
564 fn try_from(elem: ::minidom::Element) -> Result<$elem, ::error::Error> {
565 check_self!(elem, $name, $ns);
566 check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
567 let mut parsed_child = None;
568 for child in elem.children() {
569 if child.is($child_name, ::ns::$child_ns) {
570 parsed_child = Some($child_constructor::try_from(child.clone())?);
571 continue;
572 }
573 return Err(::error::Error::ParseError(concat!("Unknown child in ", $name, " element.")));
574 }
575 Ok($elem {
576 $(
577 $attr: get_attr!(elem, $attr_name, $attr_action),
578 )*
579 $child_ident: parsed_child.ok_or(::error::Error::ParseError(concat!("Missing child ", $child_name, " in ", $name, " element.")))?,
580 })
581 }
582 }
583
584 impl From<$elem> for ::minidom::Element {
585 fn from(elem: $elem) -> ::minidom::Element {
586 ::minidom::Element::builder($name)
587 .ns(::ns::$ns)
588 $(
589 .attr($attr_name, elem.$attr)
590 )*
591 .append(elem.$child_ident)
592 .build()
593 }
594 }
595 );
596}