1#[cfg(all(feature = "attribute-order", not(feature = "attribute-sorted")))]
33pub type AttributeMap<K, V> = indexmap::map::IndexMap<K, V>;
35#[cfg(all(feature = "attribute-sorted", not(feature = "attribute-order")))]
36pub type AttributeMap<K, V> = std::collections::BTreeMap<K, V>;
38#[cfg(any(
41 not(any(feature = "attribute-sorted", feature = "attribute-order")),
42 all(feature = "attribute-order", feature = "attribute-sorted")
43))]
44pub type AttributeMap<K, V> = std::collections::HashMap<K, V>;
48#[cfg(all(feature = "attribute-order", feature = "attribute-sorted"))]
51compile_error!("`attribute-order` and `attribute-sorted` are mutually exclusive — pick one");
52
53use std::borrow::Cow;
54use std::fmt;
55use std::io::{Read, Write};
56
57pub use xml::name::OwnedName as AttributeName;
58pub use xml::namespace::Namespace;
59pub use xml::reader::ParserConfig;
60use xml::reader::{EventReader, XmlEvent};
61pub use xml::writer::{EmitterConfig, Error};
62
63#[derive(Debug, Clone, PartialEq, Eq)]
64pub enum XMLNode {
65 Element(Element),
66 Comment(String),
67 CData(String),
68 Text(String),
69 ProcessingInstruction(String, Option<String>),
70}
71
72trait AttributeMapExt {
73 fn allocate(capacity: usize) -> Self;
74}
75
76#[cfg(feature = "attribute-sorted")]
77impl<K: Ord, V> AttributeMapExt for AttributeMap<K, V> {
78 fn allocate(_capacity: usize) -> Self {
79 Self::new()
80 }
81}
82
83#[cfg(not(feature = "attribute-sorted"))]
84impl<K, V> AttributeMapExt for AttributeMap<K, V> {
85 fn allocate(capacity: usize) -> Self {
86 Self::with_capacity(capacity)
87 }
88}
89
90impl XMLNode {
91 pub fn as_element(&self) -> Option<&Element> {
92 if let XMLNode::Element(e) = self {
93 Some(e)
94 } else {
95 None
96 }
97 }
98 pub fn as_mut_element(&mut self) -> Option<&mut Element> {
99 if let XMLNode::Element(e) = self {
100 Some(e)
101 } else {
102 None
103 }
104 }
105 pub fn as_comment(&self) -> Option<&str> {
106 if let XMLNode::Comment(c) = self {
107 Some(c)
108 } else {
109 None
110 }
111 }
112 pub fn as_cdata(&self) -> Option<&str> {
113 if let XMLNode::CData(c) = self {
114 Some(c)
115 } else {
116 None
117 }
118 }
119 pub fn as_text(&self) -> Option<&str> {
120 if let XMLNode::Text(c) = self {
121 Some(c)
122 } else {
123 None
124 }
125 }
126 pub fn as_processing_instruction(&self) -> Option<(&str, Option<&str>)> {
127 if let XMLNode::ProcessingInstruction(s, o) = self {
128 Some((s, o.as_ref().map(|s| s.as_str())))
129 } else {
130 None
131 }
132 }
133}
134
135#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct Element {
138 pub prefix: Option<String>,
140
141 pub namespace: Option<String>,
143
144 pub namespaces: Option<Namespace>,
148
149 pub name: String,
151
152 pub attributes: AttributeMap<AttributeName, String>,
160
161 pub children: Vec<XMLNode>,
163}
164
165#[derive(Debug)]
167pub enum ParseError {
168 MalformedXml(xml::reader::Error),
170 CannotParse,
173}
174
175impl fmt::Display for ParseError {
176 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177 match *self {
178 ParseError::MalformedXml(ref e) => write!(f, "Malformed XML. {}", e),
179 ParseError::CannotParse => write!(f, "Cannot parse"),
180 }
181 }
182}
183
184impl std::error::Error for ParseError {
185 fn description(&self) -> &str {
186 match *self {
187 ParseError::MalformedXml(..) => "Malformed XML",
188 ParseError::CannotParse => "Cannot parse",
189 }
190 }
191
192 fn cause(&self) -> Option<&dyn std::error::Error> {
193 match *self {
194 ParseError::MalformedXml(ref e) => Some(e),
195 ParseError::CannotParse => None,
196 }
197 }
198}
199
200fn build<B: Read>(reader: &mut EventReader<B>, mut elem: Element) -> Result<Element, ParseError> {
201 loop {
202 match reader.next() {
203 Ok(XmlEvent::EndElement { ref name }) => {
204 if name.local_name == elem.name {
205 return Ok(elem);
206 } else {
207 return Err(ParseError::CannotParse);
208 }
209 }
210 Ok(XmlEvent::StartElement {
211 name,
212 attributes,
213 namespace,
214 }) => {
215 let mut attr_map = AttributeMap::new();
216 for attr in attributes {
217 attr_map.insert(attr.name, attr.value);
218 }
219
220 let new_elem = Element {
221 prefix: name.prefix,
222 namespace: name.namespace,
223 namespaces: if namespace.is_essentially_empty() {
224 None
225 } else {
226 Some(namespace)
227 },
228 name: name.local_name,
229 attributes: attr_map,
230 children: Vec::new(),
231 };
232 elem.children
233 .push(XMLNode::Element(build(reader, new_elem)?));
234 }
235 Ok(XmlEvent::Characters(s)) => elem.children.push(XMLNode::Text(s)),
236 Ok(XmlEvent::Whitespace(..)) => (),
237 Ok(XmlEvent::Comment(s)) => elem.children.push(XMLNode::Comment(s)),
238 Ok(XmlEvent::CData(s)) => elem.children.push(XMLNode::CData(s)),
239 Ok(XmlEvent::ProcessingInstruction { name, data }) => elem
240 .children
241 .push(XMLNode::ProcessingInstruction(name, data)),
242 Ok(XmlEvent::StartDocument { .. }) | Ok(XmlEvent::EndDocument) => {
243 return Err(ParseError::CannotParse)
244 }
245 Ok(XmlEvent::Doctype { .. }) => (),
246 Err(e) => return Err(ParseError::MalformedXml(e)),
247 }
248 }
249}
250
251impl Element {
252 pub fn new(name: &str) -> Element {
256 Element {
257 name: String::from(name),
258 prefix: None,
259 namespace: None,
260 namespaces: None,
261 attributes: AttributeMap::new(),
262 children: Vec::new(),
263 }
264 }
265
266 pub fn parse_all<R: Read>(r: R) -> Result<Vec<XMLNode>, ParseError> {
271 let parser_config = ParserConfig::new().ignore_comments(false);
272 Element::parse_all_with_config(r, parser_config)
273 }
274
275 pub fn parse_all_with_config<R: Read>(
276 r: R,
277 parser_config: ParserConfig,
278 ) -> Result<Vec<XMLNode>, ParseError> {
279 let mut reader = EventReader::new_with_config(r, parser_config);
280 let mut root_nodes = Vec::new();
281 loop {
282 match reader.next() {
283 Ok(XmlEvent::StartElement {
284 name,
285 attributes,
286 namespace,
287 }) => {
288 let mut attr_map = AttributeMap::allocate(attributes.len());
289 for attr in attributes {
290 attr_map.insert(attr.name, attr.value);
291 }
292
293 let root = Element {
294 prefix: name.prefix,
295 namespace: name.namespace,
296 namespaces: if namespace.is_essentially_empty() {
297 None
298 } else {
299 Some(namespace)
300 },
301 name: name.local_name,
302 attributes: attr_map,
303 children: Vec::new(),
304 };
305 root_nodes.push(XMLNode::Element(build(&mut reader, root)?));
306 }
307 Ok(XmlEvent::Comment(comment_string)) => {
308 root_nodes.push(XMLNode::Comment(comment_string))
309 }
310 Ok(XmlEvent::Characters(text_string)) => {
311 root_nodes.push(XMLNode::Text(text_string))
312 }
313 Ok(XmlEvent::CData(cdata_string)) => root_nodes.push(XMLNode::CData(cdata_string)),
314 Ok(XmlEvent::Whitespace(..)) | Ok(XmlEvent::StartDocument { .. }) => continue,
315 Ok(XmlEvent::ProcessingInstruction { name, data }) => {
316 root_nodes.push(XMLNode::ProcessingInstruction(name, data))
317 }
318 Ok(XmlEvent::EndElement { .. }) => (),
319 Ok(XmlEvent::EndDocument) => return Ok(root_nodes),
320 Ok(XmlEvent::Doctype { .. }) => (),
321 Err(e) => return Err(ParseError::MalformedXml(e)),
322 }
323 }
324 }
325
326 pub fn parse<R: Read>(r: R) -> Result<Element, ParseError> {
328 let nodes = Element::parse_all(r)?;
329 for node in nodes {
330 if let XMLNode::Element(elem) = node {
331 return Ok(elem);
332 }
333 }
334 unreachable!();
336 }
337
338 pub fn parse_with_config<R: Read>(r: R, config: ParserConfig) -> Result<Element, ParseError> {
339 let nodes = Element::parse_all_with_config(r, config)?;
340 for node in nodes {
341 if let XMLNode::Element(elem) = node {
342 return Ok(elem);
343 }
344 }
345 unreachable!();
347 }
348
349 fn _write<B: Write>(&self, emitter: &mut xml::writer::EventWriter<B>) -> Result<(), Error> {
350 use xml::attribute::Attribute;
351 use xml::name::Name;
352 use xml::writer::events::XmlEvent;
353
354 let mut name = Name::local(&self.name);
355 if let Some(ref ns) = self.namespace {
356 name.namespace = Some(ns);
357 }
358 if let Some(ref p) = self.prefix {
359 name.prefix = Some(p);
360 }
361
362 let mut attributes = Vec::with_capacity(self.attributes.len());
363 for (k, v) in &self.attributes {
364 attributes.push(Attribute {
365 name: k.borrow(),
366 value: v,
367 });
368 }
369
370 let empty_ns = Namespace::empty();
371 let namespace = if let Some(ref ns) = self.namespaces {
372 Cow::Borrowed(ns)
373 } else {
374 Cow::Borrowed(&empty_ns)
375 };
376
377 emitter.write(XmlEvent::StartElement {
378 name,
379 attributes: Cow::Owned(attributes),
380 namespace,
381 })?;
382 for node in &self.children {
383 match node {
384 XMLNode::Element(elem) => elem._write(emitter)?,
385 XMLNode::Text(text) => emitter.write(XmlEvent::Characters(text))?,
386 XMLNode::Comment(comment) => emitter.write(XmlEvent::Comment(comment))?,
387 XMLNode::CData(comment) => emitter.write(XmlEvent::CData(comment))?,
388 XMLNode::ProcessingInstruction(name, data) => match data.to_owned() {
389 Some(string) => emitter.write(XmlEvent::ProcessingInstruction {
390 name,
391 data: Some(&string),
392 })?,
393 None => emitter.write(XmlEvent::ProcessingInstruction { name, data: None })?,
394 },
395 }
396 }
398 emitter.write(XmlEvent::EndElement { name: Some(name) })?;
399
400 Ok(())
401 }
402
403 pub fn write<W: Write>(&self, w: W) -> Result<(), Error> {
405 self.write_with_config(w, EmitterConfig::new())
406 }
407
408 pub fn write_with_config<W: Write>(&self, w: W, config: EmitterConfig) -> Result<(), Error> {
410 use xml::common::XmlVersion;
411 use xml::writer::events::XmlEvent;
412 use xml::writer::EventWriter;
413
414 let write_document_declaration = config.write_document_declaration;
415 let mut emitter = EventWriter::new_with_config(w, config);
416 if write_document_declaration {
417 emitter.write(XmlEvent::StartDocument {
418 version: XmlVersion::Version10,
419 encoding: None,
420 standalone: None,
421 })?;
422 }
423 self._write(&mut emitter)
424 }
425
426 pub fn get_child<P: ElementPredicate>(&self, k: P) -> Option<&Element> {
436 self.children
437 .iter()
438 .filter_map(|e| match e {
439 XMLNode::Element(elem) => Some(elem),
440 _ => None,
441 })
442 .find(|e| k.match_element(e))
443 }
444
445 pub fn get_mut_child<P: ElementPredicate>(&mut self, k: P) -> Option<&mut Element> {
447 self.children
448 .iter_mut()
449 .filter_map(|e| match e {
450 XMLNode::Element(elem) => Some(elem),
451 _ => None,
452 })
453 .find(|e| k.match_element(e))
454 }
455
456 pub fn take_child<P: ElementPredicate>(&mut self, k: P) -> Option<Element> {
458 let index = self.children.iter().position(|e| match e {
459 XMLNode::Element(elem) => k.match_element(elem),
460 _ => false,
461 });
462 match index {
463 Some(index) => match self.children.remove(index) {
464 XMLNode::Element(elem) => Some(elem),
465 _ => None,
466 },
467 None => None,
468 }
469 }
470
471 pub fn get_text<'a>(&'a self) -> Option<Cow<'a, str>> {
475 let text_nodes: Vec<&'a str> = self
476 .children
477 .iter()
478 .filter_map(|node| node.as_text().or_else(|| node.as_cdata()))
479 .collect();
480 if text_nodes.is_empty() {
481 None
482 } else if text_nodes.len() == 1 {
483 Some(Cow::Borrowed(text_nodes[0]))
484 } else {
485 let mut full_text = String::new();
486 for text in text_nodes {
487 full_text.push_str(text);
488 }
489 Some(Cow::Owned(full_text))
490 }
491 }
492 pub fn matches<P: ElementPredicate>(&self, k: P) -> bool {
494 k.match_element(self)
495 }
496
497 pub fn get_attribute<P: AttributePredicate>(&self, k: P) -> Option<&String> {
502 self.attributes
503 .iter()
504 .find(|pair| k.match_attribute(pair.0))
505 .map(|pair| pair.1)
506 }
507
508 pub fn get_mut_attribute<P: AttributePredicate>(&mut self, k: P) -> Option<&mut String> {
513 self.attributes
514 .iter_mut()
515 .find(|pair| k.match_attribute(pair.0))
516 .map(|pair| pair.1)
517 }
518
519 pub fn take_attribute<P: AttributePredicate>(&mut self, k: P) -> Option<String> {
524 if let Some(key) = self
525 .attributes
526 .keys()
527 .find(|name| k.match_attribute(name))
528 .cloned()
529 {
530 return self.attributes.remove(&key);
531 }
532 None
533 }
534}
535
536pub trait ElementPredicate {
541 fn match_element(&self, e: &Element) -> bool;
542}
543
544impl<TN> ElementPredicate for (TN,)
553where
554 String: PartialEq<TN>,
555{
556 fn match_element(&self, e: &Element) -> bool {
557 e.name == self.0
558 }
559}
560
561impl ElementPredicate for &str {
562 fn match_element(&self, e: &Element) -> bool {
564 (*self,).match_element(e)
565 }
566}
567
568impl<'a> ElementPredicate for Cow<'a, str> {
569 fn match_element(&self, e: &Element) -> bool {
571 (&**self,).match_element(e)
572 }
573}
574
575impl ElementPredicate for String {
576 fn match_element(&self, e: &Element) -> bool {
578 (&**self,).match_element(e)
579 }
580}
581
582impl<TN, NS> ElementPredicate for (TN, NS)
583where
584 String: PartialEq<TN>,
585 String: PartialEq<NS>,
586{
587 fn match_element(&self, e: &Element) -> bool {
589 e.name == self.0
590 && e.namespace
591 .as_ref()
592 .map(|ns| ns == &self.1)
593 .unwrap_or(false)
594 }
595}
596
597pub trait AttributePredicate {
602 fn match_attribute(&self, n: &AttributeName) -> bool;
603}
604
605impl AttributePredicate for (&str, Option<&str>) {
606 fn match_attribute(&self, n: &AttributeName) -> bool {
607 n.local_name == self.0
608 && match (&n.namespace, &self.1) {
609 (None, None) => true,
610 (Some(ns1), Some(ns2)) => ns1 == ns2,
611 _ => false,
612 }
613 }
614}
615
616impl AttributePredicate for &str {
617 fn match_attribute(&self, n: &AttributeName) -> bool {
619 n.local_name == *self
620 }
621}