1use crate::document::{Document, Node};
2use crate::error::{EditXMLError, Result};
3use crate::utils::HashMap;
4#[cfg(feature = "document-breakdown")]
5mod breakdown;
6#[cfg(feature = "document-breakdown")]
7pub use breakdown::*;
8mod builder;
9mod debug;
10pub use builder::ElementBuilder;
11pub use debug::ElementDebug;
12
13#[derive(Debug, Default)]
14pub(crate) struct ElementData {
15 full_name: String,
16 attributes: HashMap<String, String>, namespace_decls: HashMap<String, String>, parent: Option<Element>,
19 children: Vec<Node>,
20}
21#[derive(Debug, Clone, Copy, PartialEq)]
56pub struct Element {
57 id: usize,
58}
59
60impl Element {
61 pub fn new<S: Into<String>>(doc: &mut Document, full_name: S) -> Self {
66 Self::with_data(doc, full_name.into(), HashMap::new(), HashMap::new())
67 }
68 pub fn new_with_text(doc: &mut Document, full_name: &str, text: &str) -> Self {
78 let elem = Self::new(doc, full_name);
79 elem.set_text_content(doc, text);
80 elem
81 }
82
83 pub fn build<S: Into<String>>(name: S) -> ElementBuilder {
100 ElementBuilder::new(name.into())
101 }
102
103 pub(crate) fn with_data(
104 doc: &mut Document,
105 full_name: String,
106 attributes: HashMap<String, String>,
107 namespace_decls: HashMap<String, String>,
108 ) -> Element {
109 let elem = Element { id: doc.counter };
110 let elem_data = ElementData {
111 full_name,
112 attributes,
113 namespace_decls,
114 ..Default::default()
115 };
116 doc.store.push(elem_data);
117 doc.counter += 1;
118 elem
119 }
120
121 pub(crate) fn container() -> (Element, ElementData) {
123 let elem_data = ElementData::default();
124 let elem = Element { id: 0 };
125 (elem, elem_data)
126 }
127
128 pub fn is_container(&self) -> bool {
132 self.id == 0
133 }
134
135 #[deprecated(note = "Use Into<Node> instead. This method will be removed in future versions.")]
137 pub fn as_node(&self) -> Node {
138 self.into()
139 }
140
141 pub fn separate_prefix_name(full_name: &str) -> (&str, &str) {
145 match full_name.split_once(":") {
146 Some((prefix, name)) => (prefix, name),
147 None => ("", full_name),
148 }
149 }
150
151 pub fn debug<'element, 'doc>(
155 &'element self,
156 doc: &'doc Document,
157 ) -> ElementDebug<'element, 'doc> {
158 ElementDebug { element: self, doc }
159 }
160}
161
162impl Element {
164 fn data<'a>(&self, doc: &'a Document) -> &'a ElementData {
165 doc.store.get(self.id).unwrap()
166 }
167
168 fn mut_data<'a>(&self, doc: &'a mut Document) -> &'a mut ElementData {
169 doc.store.get_mut(self.id).unwrap()
170 }
171
172 pub fn is_root(&self, doc: &Document) -> bool {
176 self.parent(doc).map_or(false, |p| p.is_container())
177 }
178
179 pub fn full_name<'a>(&self, doc: &'a Document) -> &'a str {
182 &self.data(doc).full_name
183 }
184
185 pub fn set_full_name<S: Into<String>>(&self, doc: &mut Document, name: S) {
186 self.mut_data(doc).full_name = name.into();
187 }
188
189 pub fn prefix_name<'a>(&self, doc: &'a Document) -> (&'a str, &'a str) {
193 Self::separate_prefix_name(self.full_name(doc))
194 }
195
196 pub fn prefix<'a>(&self, doc: &'a Document) -> &'a str {
200 self.prefix_name(doc).0
201 }
202
203 pub fn set_prefix<S: Into<String>>(&self, doc: &mut Document, prefix: S) {
210 let data = self.mut_data(doc);
211 let (_, name) = Self::separate_prefix_name(&data.full_name);
212 let prefix: String = prefix.into();
213 if prefix.is_empty() {
214 data.full_name = name.to_string();
215 } else {
216 data.full_name = format!("{}:{}", prefix, name);
217 }
218 }
219
220 pub fn name<'a>(&self, doc: &'a Document) -> &'a str {
225 self.prefix_name(doc).1
226 }
227
228 pub fn set_name<S: Into<String>>(&self, doc: &mut Document, name: S) {
233 let data = self.mut_data(doc);
234 let (prefix, _) = Self::separate_prefix_name(&data.full_name);
235 if prefix.is_empty() {
236 data.full_name = name.into();
237 } else {
238 data.full_name = format!("{}:{}", prefix, name.into());
239 }
240 }
241
242 pub fn attributes<'a>(&self, doc: &'a Document) -> &'a HashMap<String, String> {
261 &self.data(doc).attributes
262 }
263
264 pub fn attribute<'a>(&self, doc: &'a Document, name: &str) -> Option<&'a str> {
266 self.attributes(doc).get(name).map(|v| v.as_str())
267 }
268
269 pub fn set_attribute<S, T>(&self, doc: &mut Document, name: S, value: T)
274 where
275 S: Into<String>,
276 T: Into<String>,
277 {
278 self.mut_attributes(doc).insert(name.into(), value.into());
279 }
280
281 pub fn mut_attributes<'a>(&self, doc: &'a mut Document) -> &'a mut HashMap<String, String> {
282 &mut self.mut_data(doc).attributes
283 }
284
285 pub fn namespace<'a>(&self, doc: &'a Document) -> Option<&'a str> {
289 self.namespace_for_prefix(doc, self.prefix(doc))
290 }
291
292 pub fn namespace_decls<'a>(&self, doc: &'a Document) -> &'a HashMap<String, String> {
296 &self.data(doc).namespace_decls
297 }
298
299 pub fn mut_namespace_decls<'a>(
300 &self,
301 doc: &'a mut Document,
302 ) -> &'a mut HashMap<String, String> {
303 &mut self.mut_data(doc).namespace_decls
304 }
305
306 pub fn set_namespace_decl<S, T>(&self, doc: &mut Document, prefix: S, namespace: T)
307 where
308 S: Into<String>,
309 T: Into<String>,
310 {
311 self.mut_namespace_decls(doc)
312 .insert(prefix.into(), namespace.into());
313 }
314
315 pub fn namespace_for_prefix<'a>(&self, doc: &'a Document, prefix: &str) -> Option<&'a str> {
318 match prefix {
319 "xml" => return Some("http://www.w3.org/XML/1998/namespace"),
320 "xmlns" => return Some("http://www.w3.org/2000/xmlns/"),
321 _ => (),
322 };
323 let mut elem = *self;
324 loop {
325 let data = elem.data(doc);
326 if let Some(value) = data.namespace_decls.get(prefix) {
327 return Some(value);
328 }
329 elem = elem.parent(doc)?;
330 }
331 }
332
333 pub(crate) fn build_text_content<'a>(&self, doc: &'a Document, buf: &'a mut String) {
334 for child in self.children(doc) {
335 child.build_text_content(doc, buf);
336 }
337 }
338
339 pub fn text_content(&self, doc: &Document) -> String {
343 let mut buf = String::new();
344 self.build_text_content(doc, &mut buf);
345 buf
346 }
347
348 pub fn set_text_content<S: Into<String>>(&self, doc: &mut Document, text: S) {
350 self.clear_children(doc);
351 let node = Node::Text(text.into());
352 self.push_child(doc, node).unwrap();
353 }
354}
355
356impl Element {
358 pub fn parent(&self, doc: &Document) -> Option<Element> {
359 self.data(doc).parent
360 }
361
362 #[inline]
364 pub fn has_parent(&self, doc: &Document) -> bool {
365 self.parent(doc).is_some()
366 }
367
368 pub fn children<'a>(&self, doc: &'a Document) -> &'a Vec<Node> {
370 &self.data(doc).children
371 }
372 pub fn push_children_recursive<'a>(&self, doc: &'a Document, nodes: &mut Vec<&'a Node>) {
376 let children = self.children(doc);
377 nodes.reserve(children.len());
378 for node in children {
379 nodes.push(node);
380 if let Node::Element(elem) = &node {
381 elem.push_children_recursive(doc, nodes);
382 }
383 }
384 }
385
386 #[inline]
388 pub fn children_recursive<'a>(&self, doc: &'a Document) -> Vec<&'a Node> {
389 let mut nodes = Vec::new();
390 self.push_children_recursive(doc, &mut nodes);
391 nodes
392 }
393
394 #[inline]
396 pub fn has_children(&self, doc: &Document) -> bool {
397 !self.children(doc).is_empty()
398 }
399 pub fn has_children_ignore_whitespace(&self, doc: &Document) -> bool {
418 self.children(doc)
419 .iter()
420 .any(|n| !n.is_text() || !n.text_content(doc).trim().is_empty())
421 }
422 pub fn child_elements(&self, doc: &Document) -> Vec<Element> {
427 self.children(doc)
428 .iter()
429 .filter_map(|node| {
430 if let Node::Element(elemid) = node {
431 Some(*elemid)
432 } else {
433 None
434 }
435 })
436 .collect()
437 }
438
439 pub fn child_elements_recursive(&self, doc: &Document) -> Vec<Element> {
441 self.children_recursive(doc)
442 .iter()
443 .filter_map(|node| {
444 if let Node::Element(elemid) = node {
445 Some(*elemid)
446 } else {
447 None
448 }
449 })
450 .collect()
451 }
452
453 pub fn find(&self, doc: &Document, name: &str) -> Option<Element> {
473 self.children(doc)
474 .iter()
475 .filter_map(|n| n.as_element())
476 .find(|e| e.name(doc) == name)
477 }
478
479 pub fn find_all(&self, doc: &Document, name: &str) -> Vec<Element> {
501 self.children(doc)
502 .iter()
503 .filter_map(|n| n.as_element())
504 .filter(|e| e.name(doc) == name)
505 .collect()
506 }
507}
508
509impl Element {
516 pub fn push_child(&self, doc: &mut Document, node: impl Into<Node>) -> Result<()> {
525 let node = node.into();
526 if let Node::Element(new_child) = node {
527 return self.push_child_element(doc, new_child);
528 }
529 self.mut_data(doc).children.push(node);
530 Ok(())
531 }
532 pub(crate) fn push_child_element(&self, doc: &mut Document, new_child: Element) -> Result<()> {
533 if new_child.is_container() {
534 return Err(EditXMLError::ContainerCannotMove);
535 }
536 let child_data = new_child.mut_data(doc);
537 if child_data.parent.is_some() {
538 return Err(EditXMLError::HasAParent);
539 }
540 child_data.parent = Some(*self);
541 self.mut_data(doc).children.push(Node::Element(new_child));
542 Ok(())
543 }
544 pub fn create_child<N, F>(&self, doc: &mut Document, name: N, f: F)
560 where
561 N: Into<String>,
562 F: FnOnce(ElementBuilder) -> ElementBuilder,
563 {
564 let elem = f(ElementBuilder::new(name.into()));
565 let elem = elem.finish(doc);
566 self.push_child_element(doc, elem).unwrap();
567 }
568 pub fn insert_child(&self, doc: &mut Document, index: usize, node: Node) -> Result<()> {
574 if let Node::Element(elem) = node {
575 if elem.is_container() {
576 return Err(EditXMLError::ContainerCannotMove);
577 }
578 let data = elem.mut_data(doc);
579 if data.parent.is_some() {
580 return Err(EditXMLError::HasAParent);
581 }
582 data.parent = Some(*self);
583 }
584 self.mut_data(doc).children.insert(index, node);
585 Ok(())
586 }
587
588 pub fn remove_child(&self, doc: &mut Document, index: usize) -> Node {
594 let node = self.mut_data(doc).children.remove(index);
595 if let Node::Element(elem) = node {
596 elem.mut_data(doc).parent = None;
597 }
598 node
599 }
600
601 pub fn pop_child(&self, doc: &mut Document) -> Option<Node> {
603 let child = self.mut_data(doc).children.pop();
604 if let Some(Node::Element(elem)) = &child {
605 elem.mut_data(doc).parent = None;
606 }
607 child
608 }
609
610 pub fn clear_children(&self, doc: &mut Document) -> Vec<Node> {
612 let count = self.children(doc).len();
613 let mut removed = Vec::with_capacity(count);
614 for _ in 0..count {
615 let child = self.remove_child(doc, 0);
616 removed.push(child);
617 }
618 removed
619 }
620
621 pub fn detach(&self, doc: &mut Document) -> Result<()> {
623 if self.is_container() {
624 return Err(EditXMLError::ContainerCannotMove);
625 }
626 let data = self.mut_data(doc);
627 if let Some(parent) = data.parent {
628 let pos = parent
629 .children(doc)
630 .iter()
631 .position(|n| n.as_element() == Some(*self))
632 .unwrap();
633 parent.remove_child(doc, pos);
634 }
635 Ok(())
636 }
637}
638
639#[cfg(test)]
640mod tests {
641 use super::{Document, Element, Node};
642
643 #[test]
644 fn test_children() {
645 let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
646 <outer>
647 inside outer
648 <middle>
649 <inner>
650 inside
651 </inner>
652 after inside
653 </middle>
654 <after>
655 inside after
656 </after>
657 </outer>
658 "#;
659 let doc = Document::parse_str(xml).unwrap();
660 let outer = doc.container().child_elements(&doc)[0];
661 let middle = outer.child_elements(&doc)[0];
662 let inner = middle.child_elements(&doc)[0];
663 let after = outer.child_elements(&doc)[1];
664 assert_eq!(doc.container().child_elements(&doc).len(), 1);
665 assert_eq!(outer.name(&doc), "outer");
666 assert_eq!(middle.name(&doc), "middle");
667 assert_eq!(inner.name(&doc), "inner");
668 assert_eq!(after.name(&doc), "after");
669 assert_eq!(outer.children(&doc).len(), 3);
670 assert_eq!(outer.child_elements(&doc).len(), 2);
671 assert_eq!(doc.container().children_recursive(&doc).len(), 8);
672 assert_eq!(
673 doc.container().child_elements_recursive(&doc),
674 vec![outer, middle, inner, after]
675 );
676 }
677
678 #[test]
679 fn test_namespace() {
680 let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
683 <root xmlns="ns" xmlns:p="pns">
684 <p:foo xmlns="inner">
685 Hello
686 </p:foo>
687 <p:bar xmlns:p="in2">
688 <c />
689 World!
690 </p:bar>
691 </root>"#;
692 let doc = Document::parse_str(xml).unwrap();
693 let container = doc.container().children(&doc)[0].as_element().unwrap();
694 let child_elements = container.child_elements(&doc);
695 let foo = *child_elements.first().unwrap();
696 let bar = *child_elements.get(1).unwrap();
697 let c = bar.child_elements(&doc)[0];
698 assert_eq!(c.prefix_name(&doc), ("", "c"));
699 assert_eq!(bar.full_name(&doc), "p:bar");
700 assert_eq!(bar.prefix(&doc), "p");
701 assert_eq!(bar.name(&doc), "bar");
702 assert_eq!(c.namespace(&doc).unwrap(), "ns");
703 assert_eq!(c.namespace_for_prefix(&doc, "p").unwrap(), "in2");
704 assert!(c.namespace_for_prefix(&doc, "random").is_none());
705 assert_eq!(bar.namespace(&doc).unwrap(), "in2");
706 assert_eq!(bar.namespace_for_prefix(&doc, "").unwrap(), "ns");
707 assert_eq!(foo.namespace(&doc).unwrap(), "pns");
708 assert_eq!(foo.namespace_for_prefix(&doc, "").unwrap(), "inner");
709 assert_eq!(foo.namespace_for_prefix(&doc, "p").unwrap(), "pns");
710 assert_eq!(container.namespace(&doc).unwrap(), "ns");
711 }
712
713 #[test]
714 fn test_find_text_content() {
715 let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
716 <core>
717 <p>Text</p>
718 <b>Text2</b>
719 </core>
720 "#;
721 let doc = Document::parse_str(xml).unwrap();
722 assert_eq!(
723 doc.root_element()
724 .unwrap()
725 .find(&doc, "p")
726 .unwrap()
727 .text_content(&doc),
728 "Text"
729 );
730 assert_eq!(
731 doc.root_element()
732 .unwrap()
733 .find(&doc, "b")
734 .unwrap()
735 .text_content(&doc),
736 "Text2"
737 );
738 assert_eq!(doc.root_element().unwrap().text_content(&doc), "TextText2")
739 }
740
741 #[test]
742 fn test_mutate_tree() -> anyhow::Result<()> {
743 let mut doc = Document::new();
745 let container = doc.container();
746 assert_eq!(container.parent(&doc), None);
747 assert_eq!(container.children(&doc).len(), 0);
748
749 let root = Element::build("root").push_to(&mut doc, container);
751 assert_eq!(root.parent(&doc).unwrap(), container);
752 assert_eq!(doc.root_element().unwrap(), root);
753
754 let a = Element::new(&mut doc, "a");
756 assert_eq!(a.parent(&doc), None);
757
758 root.push_child(&mut doc, Node::Element(a)).unwrap();
760 assert_eq!(root.children(&doc)[0].as_element().unwrap(), a);
761 assert_eq!(a.parent(&doc).unwrap(), root);
762
763 let popped = root.pop_child(&mut doc).unwrap().as_element().unwrap();
765 assert_eq!(popped, a);
766 assert_eq!(root.children(&doc).len(), 0);
767 assert_eq!(a.parent(&doc), None);
768
769 root.push_child(&mut doc, Node::Element(a)).unwrap();
771 assert_eq!(root.children(&doc)[0].as_element().unwrap(), a);
772 assert_eq!(a.parent(&doc).unwrap(), root);
773
774 root.remove_child(&mut doc, 0);
776 assert_eq!(root.children(&doc).len(), 0);
777 assert_eq!(a.parent(&doc), None);
778
779 let a = Element::new(&mut doc, "a");
781 root.insert_child(&mut doc, 0, Node::Element(a)).unwrap();
782 assert_eq!(root.children(&doc)[0].as_element().unwrap(), a);
783 assert_eq!(a.parent(&doc).unwrap(), root);
784
785 a.detach(&mut doc).unwrap();
787 assert_eq!(root.children(&doc).len(), 0);
788 assert_eq!(a.parent(&doc), None);
789 Ok(())
790 }
791}