1#[macro_export]
38macro_rules! xml {
39 ($($xml:tt)+) => {
41 $crate::xml_internal!($($xml)+)
42 };
43}
44
45#[macro_export]
48#[doc(hidden)]
49macro_rules! xml_internal {
50 (@childseq_wrapper [$first_seq_element:expr$(,$($seq_elements:expr),+)?] [$($wrapped_elements:expr,)*]) => {
51 $crate::xml_internal!(@childseq_wrapper [$($seq_elements,)*] [$($wrapped_elements,)* $crate::value::XmlChild::from($first_seq_element)])
52 };
53 (@childseq_wrapper [] [$($wrapped_elements:expr,)*]) => {
54 $crate::value::XmlSeq::from_vec(vec![$($wrapped_elements)*])
55 };
56 (@seq $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] <!--$comment:literal--> $($rest:tt)*) => {
64 $crate::xml_internal!(@seq $unwrapped_if_single $element_type [$($seq_elements,)* $crate::value::XmlComment::new($comment.as_bytes())] $($rest)*)
65 };
66 (@seq $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] <![CDATA[$cdata:literal]]> $($rest:tt)*) => {
67 $crate::xml_internal!(@seq $unwrapped_if_single $element_type [$($seq_elements,)* $crate::value::XmlCData::new($cdata.as_bytes())] $($rest)*)
68 };
69 (@seq $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] <?$target:literal $content:literal?> $($rest:tt)*) => {
70 $crate::xml_internal!(@seq $unwrapped_if_single $element_type [$($seq_elements,)* $crate::value::XmlProcessingInstruction::new($target.as_bytes(), $content.as_bytes())] $($rest)*)
71 };
72
73 (@seqelem $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] $element_name:literal {$element_namespace:expr} [$($attributes:expr),*] $attribute_name:literal:$attribute_namespace:literal = $attribute_value:literal $($rest:tt)*) => {
76 $crate::xml_internal!(@seqelem $unwrapped_if_single $element_type [$($seq_elements),*] $element_name {$element_namespace} [$($attributes,)* $crate::value::XmlAttribute::new(
77 $crate::ExpandedNameBuf::new(<$crate::LocalNameBuf as std::str::FromStr>::from_str($attribute_name).unwrap(), Some(<$crate::XmlNamespaceBuf as std::str::FromStr>::from_str($attribute_namespace).unwrap())),
78 $attribute_value
79 )] $($rest)*)
80 };
81 (@seqelem $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] $element_name:literal {$element_namespace:expr} [$($attributes:expr),*] $attribute_name:literal = $attribute_value:literal $($rest:tt)*) => {
83 $crate::xml_internal!(@seqelem $unwrapped_if_single $element_type [$($seq_elements),*] $element_name {$element_namespace} [$($attributes,)* $crate::value::XmlAttribute::new(
84 $crate::ExpandedNameBuf::new(<$crate::LocalNameBuf as std::str::FromStr>::from_str($attribute_name).unwrap(), $element_namespace),
85 $attribute_value
86 )] $($rest)*)
87 };
88 (@seqelem $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] $element_name:literal {$element_namespace:expr} [$($attributes:expr),*] /> $($rest:tt)*) => {
90 $crate::xml_internal!(@seq $unwrapped_if_single $element_type [$($seq_elements,)* $crate::value::XmlElement::new(
91 $crate::ExpandedNameBuf::new(<$crate::LocalNameBuf as std::str::FromStr>::from_str($element_name).unwrap(), $element_namespace),
92 ).with_attributes::<$crate::value::XmlAttribute, _>(vec![$($attributes),*])] $($rest)*)
93 };
94 (@seqelem $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] $element_name:literal {$element_namespace:expr} [$($attributes:expr),*] >[ $($children:tt)* ]</$name2:literal> $($rest:tt)*) => {
96 $crate::xml_internal!(@seq $unwrapped_if_single $element_type [$($seq_elements,)* {
97 assert_eq!($element_name, $name2, "Starting and ending element names must match");
98 $crate::value::XmlElement::new(
99 $crate::ExpandedNameBuf::new(<$crate::LocalNameBuf as std::str::FromStr>::from_str($element_name).unwrap(), $element_namespace),
100 ).with_attributes::<$crate::value::XmlAttribute, _>(vec![$($attributes),*])
101 .with_children::<$crate::value::XmlChild, _>($crate::xml_internal!(@seq false "child" [] $($children)*))
102 }] $($rest)*)
103 };
104
105 (@seq $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] <$element_name:literal : $element_namespace:literal $($rest:tt)*) => {
108 $crate::xml_internal!(@seqelem $unwrapped_if_single $element_type [$($seq_elements),*] $element_name {Some(<$crate::XmlNamespaceBuf as std::str::FromStr>::from_str($element_namespace).unwrap())} [] $($rest)*)
109 };
110 (@seq $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] <$element_name:literal $($rest:tt)*) => {
112 $crate::xml_internal!(@seqelem $unwrapped_if_single $element_type [$($seq_elements),*] $element_name {None} [] $($rest)*)
113 };
114
115 (@seq $unwrapped_if_single:tt $element_type:tt [$($seq_elements:expr),*] $text:literal $($rest:tt)*) => {
117 $crate::xml_internal!(@seq $unwrapped_if_single $element_type [$($seq_elements,)* $crate::value::XmlText::new($text)] $($rest)*)
118 };
119
120 (@seq true $element_type:tt [$seq_element:expr]) => {
123 $seq_element
124 };
125 (@seq $unwrapped_if_single:tt "child" [$($seq_elements:expr),*]) => {
126 <$crate::value::XmlSeq<$crate::value::XmlChild> as FromIterator<$crate::value::XmlChild>>::from_iter([$($crate::value::XmlChild::from($seq_elements)),*])
127 };
128 (@seq $unwrapped_if_single:tt "value" [$($seq_elements:expr),*]) => {
129 <$crate::value::XmlSeq<$crate::value::XmlValue> as FromIterator<$crate::value::XmlValue>>::from_iter([$($crate::value::XmlValue::from($seq_elements)),*])
130 };
131
132 (<!--$comment:literal--> $($rest:tt)*) => {
134 $crate::xml_internal!(@seq true "value" [] <!--$comment--> $($rest)*)
135 };
136 (<?$target:literal $content:literal?> $($rest:tt)*) => {
137 $crate::xml_internal!(@seq true "value" [] <?$target $content?> $($rest)*)
138 };
139 (<![CDATA[$cdata:literal]]> $($rest:tt)*) => {
140 $crate::xml_internal!(@seq true "value" [] <![CDATA[$cdata]]> $($rest)*)
141 };
142 (<$element_name:literal : $namespace:literal $($rest:tt)*) => {
143 $crate::xml_internal!(@seq true "value" [] <$element_name : $namespace $($rest)*)
144 };
145 (<$element_name:literal $($rest:tt)*) => {
146 $crate::xml_internal!(@seq true "value" [] <$element_name $($rest)*)
147 };
148 ($text:literal $($rest:tt)*) => {
149 $crate::xml_internal!(@seq true "value" [] $text $($rest)*)
150 };
151}