1#![allow(clippy::wrong_self_convention)]
90
91use std::borrow::Cow;
92use std::cmp::Ord;
93use std::cmp::Ordering;
94use std::collections::btree_map::Iter as BTreeMapIter;
95use std::collections::BTreeMap;
96use std::fmt;
97use std::hash::{Hash, Hasher};
98use std::io;
99use std::io::{Read, Write};
100use std::mem;
101use std::ops::Deref;
102use std::rc::Rc;
103use std::str::Utf8Error;
104
105use string_cache::DefaultAtom as Atom;
106
107mod xml;
108
109use crate::xml::attribute::{Attribute, OwnedAttribute};
110use crate::xml::common::Position as XmlPosition;
111use crate::xml::common::XmlVersion;
112use crate::xml::name::{Name, OwnedName};
113use crate::xml::namespace::{Namespace as XmlNamespaceMap, NS_EMPTY_URI, NS_XMLNS_URI, NS_XML_URI};
114use crate::xml::reader::{
115 Error as XmlReadError, ErrorKind as XmlReadErrorKind, EventReader, ParserConfig, XmlEvent,
116};
117use crate::xml::writer::{Error as XmlWriteError, EventWriter, XmlEvent as XmlWriteEvent};
118use crate::xml::EmitterConfig;
119
120enum XmlAtom<'a> {
121 Shared(Atom),
122 Borrowed(&'a str),
123}
124
125impl<'a> Deref for XmlAtom<'a> {
126 type Target = str;
127
128 #[inline(always)]
129 fn deref(&self) -> &str {
130 match *self {
131 XmlAtom::Shared(ref atom) => atom.deref(),
132 XmlAtom::Borrowed(s) => s,
133 }
134 }
135}
136
137impl<'a> XmlAtom<'a> {
138 #[inline(always)]
139 pub fn borrow(&self) -> &str {
140 self
141 }
142}
143
144impl<'a> fmt::Debug for XmlAtom<'a> {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 write!(f, "{:?}", self.borrow())
147 }
148}
149
150impl<'a> Clone for XmlAtom<'a> {
151 fn clone(&self) -> XmlAtom<'a> {
152 XmlAtom::Shared(Atom::from(self.borrow()))
153 }
154}
155
156impl<'a> PartialEq for XmlAtom<'a> {
157 fn eq(&self, other: &XmlAtom<'a>) -> bool {
158 self.borrow().eq(other.borrow())
159 }
160}
161
162impl<'a> Eq for XmlAtom<'a> {}
163
164impl<'a> PartialOrd for XmlAtom<'a> {
165 fn partial_cmp(&self, other: &XmlAtom<'a>) -> Option<Ordering> {
166 self.borrow().partial_cmp(other.borrow())
167 }
168}
169
170impl<'a> Ord for XmlAtom<'a> {
171 fn cmp(&self, other: &XmlAtom<'a>) -> Ordering {
172 self.borrow().cmp(other.borrow())
173 }
174}
175
176pub trait AsQName<'a> {
180 fn as_qname(&self) -> Cow<'a, QName<'a>>;
182}
183
184impl<'a> AsQName<'a> for &'a QName<'a> {
185 #[inline(always)]
186 fn as_qname(&self) -> Cow<'a, QName<'a>> {
187 Cow::Borrowed(self)
188 }
189}
190
191impl<'a> AsQName<'a> for &'a str {
192 #[inline(always)]
193 fn as_qname(&self) -> Cow<'a, QName<'a>> {
194 Cow::Owned(QName::from(self))
195 }
196}
197
198impl<'a> AsQName<'a> for (&'a str, &'a str) {
199 #[inline(always)]
200 fn as_qname(&self) -> Cow<'a, QName<'a>> {
201 Cow::Owned(QName::from_ns_name(Some(self.0), self.1))
202 }
203}
204
205#[derive(Clone)]
229pub struct QName<'a> {
230 ns: Option<XmlAtom<'a>>,
231 name: XmlAtom<'a>,
232}
233
234impl<'a> QName<'a> {
235 pub fn from(s: &'a str) -> QName<'a> {
244 let mut ns = None;
245 let mut name = None;
246 if s.starts_with('{') {
247 if let Some(index) = s.find('}') {
248 if index > 1 {
249 ns = Some(XmlAtom::Borrowed(&s[1..index]));
250 }
251 name = Some(XmlAtom::Borrowed(&s[index + 1..]));
252 }
253 }
254
255 QName {
256 ns,
257 name: name.unwrap_or(XmlAtom::Borrowed(s)),
258 }
259 }
260
261 pub fn from_name(name: &'a str) -> QName<'a> {
265 QName {
266 ns: None,
267 name: XmlAtom::Borrowed(name),
268 }
269 }
270
271 pub fn from_ns_name(ns: Option<&'a str>, name: &'a str) -> QName<'a> {
273 QName {
274 ns: ns.map(XmlAtom::Borrowed),
275 name: XmlAtom::Borrowed(name),
276 }
277 }
278
279 pub fn name(&self) -> &str {
282 &self.name
283 }
284
285 pub fn ns(&self) -> Option<&str> {
289 self.ns.as_ref().map(|x| x.borrow())
290 }
291
292 pub fn share(&self) -> QName<'static> {
296 QName {
297 name: XmlAtom::Shared(Atom::from(self.name.borrow())),
298 ns: self
299 .ns
300 .as_ref()
301 .map(|x| XmlAtom::Shared(Atom::from(x.borrow()))),
302 }
303 }
304
305 fn from_owned_name(name: OwnedName) -> QName<'static> {
306 QName {
307 name: XmlAtom::Shared(Atom::from(name.local_name)),
308 ns: match name.namespace {
309 Some(ns) => {
310 if !ns.is_empty() {
311 Some(XmlAtom::Shared(Atom::from(ns)))
312 } else {
313 None
314 }
315 }
316 _ => None,
317 },
318 }
319 }
320}
321
322impl<'a> PartialEq for QName<'a> {
323 fn eq(&self, other: &QName<'a>) -> bool {
324 self.name() == other.name() && self.ns() == other.ns()
325 }
326}
327
328impl<'a> fmt::Debug for QName<'a> {
329 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330 write!(f, "QName(\"{}\")", self)
331 }
332}
333
334impl<'a> fmt::Display for QName<'a> {
335 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336 if let Some(ref ns) = self.ns {
337 write!(f, "{{{}}}", ns.borrow())?;
338 }
339 write!(f, "{}", self.name.borrow())
340 }
341}
342
343impl<'a> Eq for QName<'a> {}
344
345impl<'a> Hash for QName<'a> {
346 fn hash<H: Hasher>(&self, state: &mut H) {
347 self.name.hash(state);
348 if let Some(ref ns) = self.ns {
349 ns.hash(state);
350 }
351 }
352}
353
354impl<'a> PartialOrd for QName<'a> {
355 fn partial_cmp(&self, other: &QName<'a>) -> Option<Ordering> {
356 (self.name(), self.ns()).partial_cmp(&(other.name(), other.ns()))
357 }
358}
359
360impl<'a> Ord for QName<'a> {
361 fn cmp(&self, other: &QName<'a>) -> Ordering {
362 (self.name(), self.ns()).cmp(&(other.name(), other.ns()))
363 }
364}
365
366#[derive(Debug, Clone)]
367struct NamespaceMap {
368 prefix_to_ns: BTreeMap<XmlAtom<'static>, XmlAtom<'static>>,
369 ns_to_prefix: BTreeMap<XmlAtom<'static>, XmlAtom<'static>>,
370}
371
372impl NamespaceMap {
373 pub fn new() -> NamespaceMap {
374 NamespaceMap {
375 prefix_to_ns: BTreeMap::new(),
376 ns_to_prefix: BTreeMap::new(),
377 }
378 }
379
380 pub fn get_prefix(&self, url: &str) -> Option<&str> {
381 let atom = XmlAtom::Borrowed(url);
383 let static_atom: &XmlAtom<'static> = unsafe { mem::transmute(&atom) };
384 self.ns_to_prefix.get(static_atom).map(|x| x.borrow())
385 }
386
387 pub fn set_prefix(&mut self, url: &str, prefix: &str) -> Result<(), Error> {
388 let prefix = XmlAtom::Shared(Atom::from(prefix));
389 if self.prefix_to_ns.contains_key(&prefix) {
390 return Err(Error::DuplicateNamespacePrefix);
391 }
392
393 let url = XmlAtom::Shared(Atom::from(url));
394 if let Some(old_prefix) = self.ns_to_prefix.remove(&url) {
395 self.prefix_to_ns.remove(&old_prefix);
396 }
397
398 self.ns_to_prefix.insert(url.clone(), prefix.clone());
399 self.prefix_to_ns.insert(prefix.clone(), url.clone());
400
401 Ok(())
402 }
403
404 fn generate_prefix(&self) -> XmlAtom<'static> {
405 let mut i = 1;
406 loop {
407 let random_prefix = format!("ns{}", i);
408 if !self
409 .prefix_to_ns
410 .contains_key(&XmlAtom::Borrowed(&random_prefix))
411 {
412 return XmlAtom::Shared(Atom::from(random_prefix));
413 }
414 i += 1;
415 }
416 }
417
418 pub fn register_if_missing(&mut self, url: &str, prefix: Option<&str>) -> bool {
419 if self.get_prefix(url).is_some() {
420 return false;
421 }
422
423 let stored_prefix = if let Some(prefix) = prefix {
424 let prefix = XmlAtom::Borrowed(prefix);
425 if self.prefix_to_ns.get(&prefix).is_some() {
426 self.generate_prefix()
427 } else {
428 XmlAtom::Shared(Atom::from(prefix.borrow()))
429 }
430 } else {
431 self.generate_prefix()
432 };
433
434 let url = XmlAtom::Shared(Atom::from(url));
435 self.prefix_to_ns.insert(stored_prefix.clone(), url.clone());
436 self.ns_to_prefix.insert(url, stored_prefix);
437 true
438 }
439}
440
441#[derive(Debug, Clone)]
473pub struct Element {
474 tag: QName<'static>,
475 attributes: BTreeMap<QName<'static>, String>,
476 children: Vec<Element>,
477 nsmap: Option<Rc<NamespaceMap>>,
478 emit_nsmap: bool,
479 text: String,
480 tail: String,
481}
482
483pub struct Children<'a> {
485 idx: usize,
486 element: &'a Element,
487}
488
489pub struct ChildrenMut<'a> {
491 iter: ::std::slice::IterMut<'a, Element>,
492}
493
494pub struct Attrs<'a> {
496 iter: BTreeMapIter<'a, QName<'a>, String>,
497}
498
499pub struct FindChildren<'a> {
501 tag: Cow<'a, QName<'a>>,
502 child_iter: Children<'a>,
503}
504
505pub struct FindChildrenMut<'a> {
507 tag: Cow<'a, QName<'a>>,
508 child_iter: ChildrenMut<'a>,
509}
510
511#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
513pub struct Position {
514 line: u64,
515 column: u64,
516}
517
518impl Position {
519 pub fn new(line: u64, column: u64) -> Position {
521 Position { line, column }
522 }
523
524 fn from_xml_position(pos: &dyn XmlPosition) -> Position {
525 let pos = pos.position();
526 Position::new(pos.row, pos.column)
527 }
528
529 pub fn line(&self) -> u64 {
531 self.line
532 }
533 pub fn column(&self) -> u64 {
535 self.column
536 }
537}
538
539impl fmt::Display for Position {
540 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
541 write!(f, "{}:{}", self.line, self.column)
542 }
543}
544
545#[derive(Debug)]
547pub enum Error {
548 MalformedXml {
550 msg: Cow<'static, str>,
551 pos: Position,
552 },
553 Io(io::Error),
555 Utf8(Utf8Error),
557 UnexpectedEvent {
560 msg: Cow<'static, str>,
561 pos: Position,
562 },
563 DuplicateNamespacePrefix,
565}
566
567impl Error {
568 pub fn position(&self) -> Option<Position> {
570 match self {
571 Error::MalformedXml { pos, .. } => Some(*pos),
572 Error::UnexpectedEvent { pos, .. } => Some(*pos),
573 _ => None,
574 }
575 }
576
577 pub fn line(&self) -> u64 {
579 self.position().map(|x| x.line()).unwrap_or(0)
580 }
581
582 pub fn column(&self) -> u64 {
584 self.position().map(|x| x.column()).unwrap_or(0)
585 }
586}
587
588impl fmt::Display for Error {
589 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
590 match *self {
591 Error::MalformedXml { ref pos, ref msg } => {
592 write!(f, "Malformed XML: {} ({})", msg, pos)
593 }
594 Error::Io(ref e) => write!(f, "{}", e),
595 Error::Utf8(ref e) => write!(f, "{}", e),
596 Error::UnexpectedEvent { ref msg, .. } => write!(f, "Unexpected XML event: {}", msg),
597 Error::DuplicateNamespacePrefix => {
598 write!(f, "Encountered duplicated namespace prefix")
599 }
600 }
601 }
602}
603
604impl std::error::Error for Error {
605 fn cause(&self) -> Option<&dyn std::error::Error> {
606 match *self {
607 Error::Io(ref e) => Some(e),
608 Error::Utf8(ref e) => Some(e),
609 _ => None,
610 }
611 }
612}
613
614impl From<XmlReadError> for Error {
615 fn from(err: XmlReadError) -> Error {
616 match *err.kind() {
617 XmlReadErrorKind::Io(ref err) => Error::Io(io::Error::new(err.kind(), err.to_string())),
618 XmlReadErrorKind::Utf8(err) => Error::Utf8(err),
619 XmlReadErrorKind::UnexpectedEof => Error::Io(io::Error::new(
620 io::ErrorKind::UnexpectedEof,
621 "Encountered unexpected eof",
622 )),
623 XmlReadErrorKind::Syntax(ref msg) => Error::MalformedXml {
624 msg: msg.clone(),
625 pos: Position::from_xml_position(&err),
626 },
627 }
628 }
629}
630
631impl From<XmlWriteError> for Error {
632 fn from(err: XmlWriteError) -> Error {
633 match err {
634 XmlWriteError::Io(err) => Error::Io(err),
635 err => Err(err).unwrap(),
636 }
637 }
638}
639
640impl<'a> Iterator for Children<'a> {
641 type Item = &'a Element;
642
643 fn next(&mut self) -> Option<&'a Element> {
644 if self.idx < self.element.children.len() {
645 let rv = &self.element.children[self.idx];
646 self.idx += 1;
647 Some(rv)
648 } else {
649 None
650 }
651 }
652}
653
654impl<'a> Iterator for ChildrenMut<'a> {
655 type Item = &'a mut Element;
656
657 fn next(&mut self) -> Option<&'a mut Element> {
658 self.iter.next()
659 }
660}
661
662impl<'a> Iterator for Attrs<'a> {
663 type Item = (&'a QName<'a>, &'a str);
664
665 fn next(&mut self) -> Option<(&'a QName<'a>, &'a str)> {
666 if let Some((k, v)) = self.iter.next() {
667 Some((k, v.as_str()))
668 } else {
669 None
670 }
671 }
672}
673
674impl<'a> Iterator for FindChildren<'a> {
675 type Item = &'a Element;
676
677 fn next(&mut self) -> Option<&'a Element> {
678 use std::borrow::Borrow;
679 loop {
680 if let Some(child) = self.child_iter.next() {
681 if child.tag() == self.tag.borrow() {
682 return Some(child);
683 }
684 } else {
685 return None;
686 }
687 }
688 }
689}
690
691impl<'a> Iterator for FindChildrenMut<'a> {
692 type Item = &'a mut Element;
693
694 fn next(&mut self) -> Option<&'a mut Element> {
695 use std::borrow::Borrow;
696 let tag: &QName = self.tag.borrow();
697 self.child_iter.find(|x| x.tag() == tag)
698 }
699}
700
701impl Element {
702 pub fn new<'a, Q: AsQName<'a>>(tag: Q) -> Element {
709 Element::new_with_nsmap(&tag.as_qname(), None)
710 }
711
712 pub fn new_with_namespaces<'a, Q: AsQName<'a>>(tag: Q, reference: &Element) -> Element {
719 Element::new_with_nsmap(&tag.as_qname(), reference.nsmap.clone())
720 }
721
722 fn new_with_nsmap(tag: &QName<'_>, nsmap: Option<Rc<NamespaceMap>>) -> Element {
723 let mut rv = Element {
724 tag: tag.share(),
725 attributes: BTreeMap::new(),
726 nsmap,
727 emit_nsmap: false,
728 children: vec![],
729 text: String::new(),
730 tail: String::new(),
731 };
732 if let Some(url) = tag.ns() {
733 let prefix = rv.get_namespace_prefix(url).unwrap_or("").to_string();
734 rv.register_namespace(url, Some(&prefix));
735 }
736 rv
737 }
738
739 pub fn from_reader<R: Read>(r: R) -> Result<Element, Error> {
741 let cfg = ParserConfig::new();
742 let mut reader = cfg.create_reader(r);
743 loop {
744 match reader.next_event() {
745 Ok(XmlEvent::StartElement {
746 name,
747 attributes,
748 namespace,
749 }) => {
750 return Element::from_start_element(
751 name,
752 attributes,
753 namespace,
754 None,
755 &mut reader,
756 );
757 }
758 Ok(XmlEvent::StartDocument { .. }) | Ok(XmlEvent::ProcessingInstruction { .. }) => {
759 continue;
760 }
761 Ok(_) => {
762 return Err(Error::UnexpectedEvent {
763 msg: Cow::Borrowed("xml construct"),
764 pos: Position::from_xml_position(&reader),
765 })
766 }
767 Err(e) => return Err(e.into()),
768 }
769 }
770 }
771
772 pub fn to_writer<W: Write>(&self, w: W) -> Result<(), Error> {
784 self.to_writer_with_options(w, WriteOptions::new())
785 }
786
787 pub fn to_writer_with_options<W: Write>(
799 &self,
800 w: W,
801 options: WriteOptions,
802 ) -> Result<(), Error> {
803 let mut writer = options.emitter_config.clone().create_writer(w);
804
805 if options.xml_prolog.is_some() {
806 writer.write(XmlWriteEvent::StartDocument {
807 version: match options.xml_prolog.unwrap() {
808 XmlProlog::Version10 => XmlVersion::Version10,
809 XmlProlog::Version11 => XmlVersion::Version11,
810 },
811 encoding: Some("utf-8"),
812 standalone: None,
813 })?;
814 }
815
816 self.dump_into_writer(&mut writer)
817 }
818
819 pub fn to_string(&self) -> Result<String, Error> {
821 let mut out: Vec<u8> = Vec::new();
822 self.to_writer(&mut out)?;
823 Ok(String::from_utf8(out).unwrap())
824 }
825
826 fn get_xml_name<'a>(&'a self, qname: &'a QName<'a>) -> Name<'a> {
827 let mut name = Name::local(qname.name());
828 if let Some(url) = qname.ns() {
829 name.namespace = Some(url);
830 if let Some(prefix) = self.get_namespace_prefix(url) {
831 if !prefix.is_empty() {
832 name.prefix = Some(prefix);
833 }
834 }
835 }
836 name
837 }
838
839 fn dump_into_writer<W: Write>(&self, w: &mut EventWriter<W>) -> Result<(), Error> {
840 let name = self.get_xml_name(&self.tag);
841
842 let mut attributes = Vec::with_capacity(self.attributes.len());
843 for (k, v) in self.attributes.iter() {
844 attributes.push(Attribute {
845 name: self.get_xml_name(k),
846 value: v,
847 });
848 }
849
850 let mut namespace = XmlNamespaceMap::empty();
851 if self.emit_nsmap {
852 if let Some(ref nsmap) = self.nsmap {
853 for (prefix, url) in &nsmap.prefix_to_ns {
854 namespace.put(prefix.borrow(), url.borrow());
855 }
856 }
857 }
858
859 w.write(XmlWriteEvent::StartElement {
860 name,
861 attributes: Cow::Owned(attributes),
862 namespace: Cow::Owned(namespace),
863 })?;
864
865 let text = self.text();
866 if !text.is_empty() {
867 w.write(XmlWriteEvent::Characters(text))?;
868 }
869
870 for elem in &self.children {
871 elem.dump_into_writer(w)?;
872 let text = elem.tail();
873 if !text.is_empty() {
874 w.write(XmlWriteEvent::Characters(text))?;
875 }
876 }
877
878 w.write(XmlWriteEvent::EndElement { name: Some(name) })?;
879
880 Ok(())
881 }
882
883 fn from_start_element<R: Read>(
884 name: OwnedName,
885 attributes: Vec<OwnedAttribute>,
886 namespace: XmlNamespaceMap,
887 parent_nsmap: Option<Rc<NamespaceMap>>,
888 reader: &mut EventReader<R>,
889 ) -> Result<Element, Error> {
890 let mut root = Element {
891 tag: QName::from_owned_name(name),
892 attributes: BTreeMap::new(),
893 nsmap: parent_nsmap,
894 emit_nsmap: false,
895 children: vec![],
896 text: String::new(),
897 tail: String::new(),
898 };
899 for attr in attributes {
900 root.attributes
901 .insert(QName::from_owned_name(attr.name), attr.value);
902 }
903
904 if !namespace.is_essentially_empty() {
905 for (prefix, url) in namespace.0.iter() {
906 root.register_namespace(url, Some(prefix));
907 }
908 };
909
910 root.parse_children(reader)?;
911 Ok(root)
912 }
913
914 fn parse_children<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
915 loop {
916 match reader.next_event() {
917 Ok(XmlEvent::EndElement { ref name }) => {
918 if name.local_name == self.tag.name()
919 && name.namespace.as_deref() == self.tag.ns()
920 {
921 return Ok(());
922 } else {
923 return Err(Error::UnexpectedEvent {
924 msg: Cow::Owned(format!("Unexpected end element {}", &name.local_name)),
925 pos: Position::from_xml_position(reader),
926 });
927 }
928 }
929 Ok(XmlEvent::StartElement {
930 name,
931 attributes,
932 namespace,
933 }) => {
934 self.children.push(Element::from_start_element(
935 name,
936 attributes,
937 namespace,
938 self.nsmap.clone(),
939 reader,
940 )?);
941 }
942 Ok(XmlEvent::Characters(s)) => {
943 let child_count = self.children.len();
944 if child_count > 0 {
945 self.children[child_count - 1].tail = s;
946 } else {
947 self.text = s;
948 }
949 }
950 Ok(XmlEvent::StartDocument { .. }) | Ok(XmlEvent::ProcessingInstruction { .. }) => {
951 continue;
952 }
953 Ok(_) => {
954 return Err(Error::UnexpectedEvent {
955 msg: Cow::Borrowed("unknown element"),
956 pos: Position::from_xml_position(reader),
957 })
958 }
959 Err(e) => {
960 return Err(e.into());
961 }
962 }
963 }
964 }
965
966 pub fn text(&self) -> &str {
971 &self.text
972 }
973
974 pub fn set_text<S: Into<String>>(&mut self, value: S) -> &mut Element {
976 self.text = value.into();
977 self
978 }
979
980 pub fn tail(&self) -> &str {
984 &self.tail
985 }
986
987 pub fn set_tail<S: Into<String>>(&mut self, value: S) -> &mut Element {
989 self.tail = value.into();
990 self
991 }
992
993 pub fn tag(&self) -> &QName {
998 &self.tag
999 }
1000
1001 pub fn set_tag<'a>(&mut self, tag: &QName<'a>) -> &mut Element {
1003 self.tag = tag.share();
1004 self
1005 }
1006
1007 pub fn child_count(&self) -> usize {
1009 self.children.len()
1010 }
1011
1012 pub fn get_child(&self, idx: usize) -> Option<&Element> {
1014 self.children.get(idx)
1015 }
1016
1017 pub fn get_child_mut(&mut self, idx: usize) -> Option<&mut Element> {
1019 self.children.get_mut(idx)
1020 }
1021
1022 pub fn remove_child(&mut self, idx: usize) -> Option<Element> {
1027 if self.children.len() > idx {
1028 Some(self.children.remove(idx))
1029 } else {
1030 None
1031 }
1032 }
1033
1034 pub fn retain_children<F>(&mut self, f: F)
1036 where
1037 F: FnMut(&Element) -> bool,
1038 {
1039 self.children.retain(f);
1040 }
1041
1042 pub fn retain_children_mut<F>(&mut self, mut f: F)
1044 where
1045 F: FnMut(&mut Element) -> bool,
1046 {
1047 let old_children = std::mem::take(&mut self.children);
1049 self.children
1050 .extend(old_children.into_iter().filter_map(|mut item| {
1051 if f(&mut item) {
1052 Some(item)
1053 } else {
1054 None
1055 }
1056 }));
1057 }
1058
1059 pub fn append_child(&mut self, child: Element) -> &mut Element {
1061 self.children.push(child);
1062 self
1063 }
1064
1065 pub fn append_new_child<'a, Q: AsQName<'a>>(&'a mut self, tag: Q) -> &'a mut Element {
1084 let child = Element::new_with_namespaces(tag, self);
1085 self.append_child(child);
1086 let idx = self.children.len() - 1;
1087 &mut self.children[idx]
1088 }
1089
1090 pub fn children(&self) -> Children<'_> {
1092 Children {
1093 idx: 0,
1094 element: self,
1095 }
1096 }
1097
1098 pub fn children_mut(&mut self) -> ChildrenMut<'_> {
1100 ChildrenMut {
1101 iter: self.children.iter_mut(),
1102 }
1103 }
1104
1105 pub fn find_all<'a, Q: AsQName<'a>>(&'a self, tag: Q) -> FindChildren<'a> {
1107 FindChildren {
1108 tag: tag.as_qname(),
1109 child_iter: self.children(),
1110 }
1111 }
1112
1113 pub fn find_all_mut<'a, Q: AsQName<'a>>(&'a mut self, tag: Q) -> FindChildrenMut<'a> {
1115 FindChildrenMut {
1116 tag: tag.as_qname(),
1117 child_iter: self.children_mut(),
1118 }
1119 }
1120
1121 pub fn find<'a, Q: AsQName<'a>>(&'a self, tag: Q) -> Option<&'a Element> {
1123 use std::borrow::Borrow;
1124 let tag = tag.as_qname();
1125
1126 for child in self.children() {
1127 if child.tag() == tag.borrow() {
1128 return Some(child);
1129 }
1130 }
1131 None
1132 }
1133
1134 pub fn find_mut<'a, Q: AsQName<'a>>(&'a mut self, tag: Q) -> Option<&'a mut Element> {
1136 self.find_all_mut(tag).next()
1137 }
1138
1139 pub fn get_attr<'a, Q: AsQName<'a>>(&'a self, name: Q) -> Option<&'a str> {
1141 self.attributes.get(&name.as_qname()).map(|x| x.as_str())
1142 }
1143
1144 pub fn set_attr<'a, Q: AsQName<'a>, S: Into<String>>(
1148 &'a mut self,
1149 name: Q,
1150 value: S,
1151 ) -> &'a mut Element {
1152 self.attributes
1153 .insert(name.as_qname().share(), value.into());
1154 self
1155 }
1156
1157 pub fn remove_attr<'a, Q: AsQName<'a>>(&'a mut self, name: Q) -> Option<String> {
1159 use std::borrow::Borrow;
1170 let name = name.as_qname();
1171 let name_ref: &QName<'a> = name.borrow();
1172 let name_ref_static: &QName<'static> = unsafe { mem::transmute(name_ref) };
1173 self.attributes.remove(name_ref_static)
1174 }
1175
1176 pub fn attrs(&self) -> Attrs<'_> {
1178 Attrs {
1179 iter: self.attributes.iter(),
1180 }
1181 }
1182
1183 pub fn attr_count(&self) -> usize {
1185 self.attributes.len()
1186 }
1187
1188 fn get_nsmap_mut(&mut self) -> &mut NamespaceMap {
1189 let new_map = match self.nsmap {
1190 Some(ref mut nsmap) if Rc::strong_count(nsmap) == 1 => None,
1191 Some(ref mut nsmap) => Some(Rc::new((**nsmap).clone())),
1192 None => Some(Rc::new(NamespaceMap::new())),
1193 };
1194 if let Some(nsmap) = new_map {
1195 self.nsmap = Some(nsmap);
1196 }
1197 Rc::get_mut(self.nsmap.as_mut().unwrap()).unwrap()
1198 }
1199
1200 pub fn register_namespace(&mut self, url: &str, prefix: Option<&str>) {
1208 if self.get_namespace_prefix(url).is_none()
1209 && self.get_nsmap_mut().register_if_missing(url, prefix)
1210 {
1211 self.emit_nsmap = true;
1212 }
1213 }
1214
1215 pub fn set_namespace_prefix(&mut self, url: &str, prefix: &str) -> Result<(), Error> {
1222 if self.get_namespace_prefix(url) == Some(prefix) {
1223 Ok(())
1224 } else {
1225 self.get_nsmap_mut().set_prefix(url, prefix)
1226 }
1227 }
1228
1229 pub fn get_namespace_prefix(&self, url: &str) -> Option<&str> {
1231 match url {
1232 NS_EMPTY_URI => Some(""),
1233 NS_XML_URI => Some("xml"),
1234 NS_XMLNS_URI => Some("xmlns"),
1235 _ => {
1236 if let Some(ref nsmap) = self.nsmap {
1237 nsmap.get_prefix(url)
1238 } else {
1239 None
1240 }
1241 }
1242 }
1243 }
1244
1245 pub fn navigate<'a, Q: AsQName<'a>>(&'a self, path: &[Q]) -> Option<&'a Element> {
1247 use std::borrow::Borrow;
1248 let mut node = self;
1249
1250 'outer: for piece in path {
1251 let reftag = piece.as_qname();
1252 for child in node.children() {
1253 if child.tag() == reftag.borrow() {
1254 node = child;
1255 continue 'outer;
1256 }
1257 }
1258 return None;
1259 }
1260
1261 Some(node)
1262 }
1263}
1264
1265pub enum XmlProlog {
1267 Version10,
1268 Version11,
1269}
1270
1271pub struct WriteOptions {
1273 emitter_config: EmitterConfig,
1274 xml_prolog: Option<XmlProlog>,
1275}
1276
1277impl Default for WriteOptions {
1278 fn default() -> WriteOptions {
1279 WriteOptions {
1280 emitter_config: EmitterConfig::new(),
1281 xml_prolog: Some(XmlProlog::Version10),
1282 }
1283 }
1284}
1285
1286impl WriteOptions {
1287 pub fn new() -> WriteOptions {
1288 WriteOptions {
1289 ..WriteOptions::default()
1290 }
1291 }
1292
1293 pub fn set_xml_prolog(mut self, prolog: Option<XmlProlog>) -> Self {
1299 self.emitter_config = self
1300 .emitter_config
1301 .write_document_declaration(prolog.is_some());
1302 self.xml_prolog = prolog;
1303
1304 self
1305 }
1306
1307 pub fn set_line_separator<I: Into<Cow<'static, str>>>(mut self, sep: I) -> Self {
1309 self.emitter_config = self.emitter_config.line_separator(sep.into());
1310 self
1311 }
1312
1313 pub fn set_indent_string<I: Into<Cow<'static, str>>>(mut self, indent: I) -> Self {
1316 self.emitter_config = self.emitter_config.indent_string(indent.into());
1317 self
1318 }
1319
1320 pub fn set_perform_indent(mut self, yes: bool) -> Self {
1330 self.emitter_config = self.emitter_config.perform_indent(yes);
1331 self
1332 }
1333
1334 pub fn set_normalize_empty_elements(mut self, yes: bool) -> Self {
1339 self.emitter_config = self.emitter_config.normalize_empty_elements(yes);
1340 self
1341 }
1342
1343 pub fn set_cdata_to_characters(mut self, yes: bool) -> Self {
1349 self.emitter_config = self.emitter_config.cdata_to_characters(yes);
1350 self
1351 }
1352
1353 pub fn set_pad_self_closing(mut self, yes: bool) -> Self {
1361 self.emitter_config = self.emitter_config.pad_self_closing(yes);
1362 self
1363 }
1364
1365 pub fn set_autopad_comments(mut self, yes: bool) -> Self {
1372 self.emitter_config = self.emitter_config.autopad_comments(yes);
1373 self
1374 }
1375}