1use crate::document::{Document, Node};
2use crate::error::{Error, Result};
3use std::collections::HashMap;
4
5#[derive(Debug)]
6pub(crate) struct ElementData {
7 full_name: String,
8 attributes: HashMap<String, String>, namespace_decls: HashMap<String, String>, parent: Option<Element>,
11 children: Vec<Node>,
12}
13
14pub struct ElementBuilder<'a> {
46 element: Element,
47 doc: &'a mut Document,
48}
49
50impl<'a> ElementBuilder<'a> {
51 fn new(element: Element, doc: &'a mut Document) -> ElementBuilder<'a> {
52 ElementBuilder { element, doc }
53 }
54
55 pub fn prefix<S: Into<String>>(self, prefix: S) -> Self {
57 self.element.set_prefix(self.doc, prefix);
58 self
59 }
60
61 pub fn attribute<S, T>(self, name: S, value: T) -> Self
62 where
63 S: Into<String>,
64 T: Into<String>,
65 {
66 self.element.set_attribute(self.doc, name, value);
67 self
68 }
69
70 pub fn namespace_decl<S, T>(self, prefix: S, namespace: T) -> Self
71 where
72 S: Into<String>,
73 T: Into<String>,
74 {
75 self.element.set_namespace_decl(self.doc, prefix, namespace);
76 self
77 }
78
79 pub fn text_content<S: Into<String>>(self, text: S) -> Self {
80 self.element.set_text_content(self.doc, text);
81 self
82 }
83
84 pub fn finish(self) -> Element {
85 self.element
86 }
87
88 pub fn push_to(self, parent: Element) -> Element {
90 self.element.push_to(self.doc, parent).unwrap();
91 self.element
92 }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub struct Element {
131 id: usize,
132}
133
134impl Element {
135 pub fn new<S: Into<String>>(doc: &mut Document, full_name: S) -> Self {
140 Self::with_data(doc, full_name.into(), HashMap::new(), HashMap::new())
141 }
142
143 pub fn build<S: Into<String>>(doc: &mut Document, name: S) -> ElementBuilder {
160 let element = Self::new(doc, name);
161 ElementBuilder::new(element, doc)
162 }
163
164 pub(crate) fn with_data(
165 doc: &mut Document,
166 full_name: String,
167 attributes: HashMap<String, String>,
168 namespace_decls: HashMap<String, String>,
169 ) -> Element {
170 let elem = Element { id: doc.counter };
171 let elem_data = ElementData {
172 full_name,
173 attributes,
174 namespace_decls,
175 parent: None,
176 children: vec![],
177 };
178 doc.store.push(elem_data);
179 doc.counter += 1;
180 elem
181 }
182
183 pub(crate) fn container() -> (Element, ElementData) {
185 let elem_data = ElementData {
186 full_name: String::new(),
187 attributes: HashMap::new(),
188 namespace_decls: HashMap::new(),
189 parent: None,
190 children: Vec::new(),
191 };
192 let elem = Element { id: 0 };
193 (elem, elem_data)
194 }
195
196 pub fn is_container(&self) -> bool {
200 self.id == 0
201 }
202
203 pub fn as_node(&self) -> Node {
205 Node::Element(*self)
206 }
207
208 pub fn separate_prefix_name(full_name: &str) -> (&str, &str) {
212 match full_name.split_once(":") {
213 Some((prefix, name)) => (prefix, name),
214 None => ("", full_name),
215 }
216 }
217}
218
219impl Element {
221 fn data<'a>(&self, doc: &'a Document) -> &'a ElementData {
222 doc.store.get(self.id).unwrap()
223 }
224
225 fn mut_data<'a>(&self, doc: &'a mut Document) -> &'a mut ElementData {
226 doc.store.get_mut(self.id).unwrap()
227 }
228
229 pub fn is_root(&self, doc: &Document) -> bool {
233 self.parent(doc).map_or(false, |p| p.is_container())
234 }
235
236 pub fn full_name<'a>(&self, doc: &'a Document) -> &'a str {
239 &self.data(doc).full_name
240 }
241
242 pub fn set_full_name<S: Into<String>>(&self, doc: &mut Document, name: S) {
243 self.mut_data(doc).full_name = name.into();
244 }
245
246 pub fn prefix_name<'a>(&self, doc: &'a Document) -> (&'a str, &'a str) {
250 Self::separate_prefix_name(self.full_name(doc))
251 }
252
253 pub fn prefix<'a>(&self, doc: &'a Document) -> &'a str {
257 self.prefix_name(doc).0
258 }
259
260 pub fn set_prefix<S: Into<String>>(&self, doc: &mut Document, prefix: S) {
267 let data = self.mut_data(doc);
268 let (_, name) = Self::separate_prefix_name(&data.full_name);
269 let prefix: String = prefix.into();
270 if prefix.is_empty() {
271 data.full_name = name.to_string();
272 } else {
273 data.full_name = format!("{}:{}", prefix, name);
274 }
275 }
276
277 pub fn name<'a>(&self, doc: &'a Document) -> &'a str {
282 self.prefix_name(doc).1
283 }
284
285 pub fn set_name<S: Into<String>>(&self, doc: &mut Document, name: S) {
290 let data = self.mut_data(doc);
291 let (prefix, _) = Self::separate_prefix_name(&data.full_name);
292 if prefix.is_empty() {
293 data.full_name = name.into();
294 } else {
295 data.full_name = format!("{}:{}", prefix, name.into());
296 }
297 }
298
299 pub fn attributes<'a>(&self, doc: &'a Document) -> &'a HashMap<String, String> {
318 &self.data(doc).attributes
319 }
320
321 pub fn attribute<'a>(&self, doc: &'a Document, name: &str) -> Option<&'a str> {
323 self.attributes(doc).get(name).map(|v| v.as_str())
324 }
325
326 pub fn set_attribute<S, T>(&self, doc: &mut Document, name: S, value: T)
331 where
332 S: Into<String>,
333 T: Into<String>,
334 {
335 self.mut_attributes(doc).insert(name.into(), value.into());
336 }
337
338 pub fn mut_attributes<'a>(&self, doc: &'a mut Document) -> &'a mut HashMap<String, String> {
339 &mut self.mut_data(doc).attributes
340 }
341
342 pub fn namespace<'a>(&self, doc: &'a Document) -> Option<&'a str> {
346 self.namespace_for_prefix(doc, self.prefix(doc))
347 }
348
349 pub fn namespace_decls<'a>(&self, doc: &'a Document) -> &'a HashMap<String, String> {
353 &self.data(doc).namespace_decls
354 }
355
356 pub fn mut_namespace_decls<'a>(
357 &self,
358 doc: &'a mut Document,
359 ) -> &'a mut HashMap<String, String> {
360 &mut self.mut_data(doc).namespace_decls
361 }
362
363 pub fn set_namespace_decl<S, T>(&self, doc: &mut Document, prefix: S, namespace: T)
364 where
365 S: Into<String>,
366 T: Into<String>,
367 {
368 self.mut_namespace_decls(doc)
369 .insert(prefix.into(), namespace.into());
370 }
371
372 pub fn namespace_for_prefix<'a>(&self, doc: &'a Document, prefix: &str) -> Option<&'a str> {
375 match prefix {
376 "xml" => return Some("http://www.w3.org/XML/1998/namespace"),
377 "xmlns" => return Some("http://www.w3.org/2000/xmlns/"),
378 _ => (),
379 };
380 let mut elem = *self;
381 loop {
382 let data = elem.data(doc);
383 if let Some(value) = data.namespace_decls.get(prefix) {
384 return Some(value);
385 }
386 elem = elem.parent(doc)?;
387 }
388 }
389
390 pub(crate) fn build_text_content<'a>(&self, doc: &'a Document, buf: &'a mut String) {
391 for child in self.children(doc) {
392 child.build_text_content(doc, buf);
393 }
394 }
395
396 pub fn text_content(&self, doc: &Document) -> String {
400 let mut buf = String::new();
401 self.build_text_content(doc, &mut buf);
402 buf
403 }
404
405 pub fn set_text_content<S: Into<String>>(&self, doc: &mut Document, text: S) {
407 self.clear_children(doc);
408 let node = Node::Text(text.into());
409 self.push_child(doc, node).unwrap();
410 }
411}
412
413impl Element {
415 pub fn parent(&self, doc: &Document) -> Option<Element> {
416 self.data(doc).parent
417 }
418
419 pub fn has_parent(&self, doc: &Document) -> bool {
421 self.parent(doc).is_some()
422 }
423
424 pub fn children<'a>(&self, doc: &'a Document) -> &'a Vec<Node> {
426 &self.data(doc).children
427 }
428
429 fn _children_recursive<'a>(&self, doc: &'a Document, nodes: &mut Vec<&'a Node>) {
430 for node in self.children(doc) {
431 nodes.push(node);
432 if let Node::Element(elem) = &node {
433 elem._children_recursive(doc, nodes);
434 }
435 }
436 }
437
438 pub fn children_recursive<'a>(&self, doc: &'a Document) -> Vec<&'a Node> {
440 let mut nodes = Vec::new();
441 self._children_recursive(doc, &mut nodes);
442 nodes
443 }
444
445 pub fn has_children(&self, doc: &Document) -> bool {
447 !self.children(doc).is_empty()
448 }
449
450 pub fn child_elements(&self, doc: &Document) -> Vec<Element> {
455 self.children(doc)
456 .iter()
457 .filter_map(|node| {
458 if let Node::Element(elemid) = node {
459 Some(*elemid)
460 } else {
461 None
462 }
463 })
464 .collect()
465 }
466
467 pub fn child_elements_recursive(&self, doc: &Document) -> Vec<Element> {
469 self.children_recursive(doc)
470 .iter()
471 .filter_map(|node| {
472 if let Node::Element(elemid) = node {
473 Some(*elemid)
474 } else {
475 None
476 }
477 })
478 .collect()
479 }
480
481 pub fn find(&self, doc: &Document, name: &str) -> Option<Element> {
483 self.children(doc)
484 .iter()
485 .filter_map(|n| n.as_element())
486 .find(|e| e.name(doc) == name)
487 }
488
489 pub fn find_all(&self, doc: &Document, name: &str) -> Vec<Element> {
491 self.children(doc)
492 .iter()
493 .filter_map(|n| n.as_element())
494 .filter(|e| e.name(doc) == name)
495 .collect()
496 }
497}
498
499impl Element {
506 pub fn push_child(&self, doc: &mut Document, node: Node) -> Result<()> {
513 if let Node::Element(elem) = node {
514 if elem.is_container() {
515 return Err(Error::ContainerCannotMove);
516 }
517 let data = elem.mut_data(doc);
518 if data.parent.is_some() {
519 return Err(Error::HasAParent);
520 }
521 data.parent = Some(*self);
522 }
523 self.mut_data(doc).children.push(node);
524 Ok(())
525 }
526
527 pub fn push_to(&self, doc: &mut Document, parent: Element) -> Result<()> {
535 parent.push_child(doc, self.as_node())
536 }
537
538 pub fn insert_child(&self, doc: &mut Document, index: usize, node: Node) -> Result<()> {
550 if let Node::Element(elem) = node {
551 if elem.is_container() {
552 return Err(Error::ContainerCannotMove);
553 }
554 let data = elem.mut_data(doc);
555 if data.parent.is_some() {
556 return Err(Error::HasAParent);
557 }
558 data.parent = Some(*self);
559 }
560 self.mut_data(doc).children.insert(index, node);
561 Ok(())
562 }
563
564 pub fn remove_child(&self, doc: &mut Document, index: usize) -> Node {
570 let node = self.mut_data(doc).children.remove(index);
571 if let Node::Element(elem) = node {
572 elem.mut_data(doc).parent = None;
573 }
574 node
575 }
576
577 pub fn pop_child(&self, doc: &mut Document) -> Option<Node> {
579 let child = self.mut_data(doc).children.pop();
580 if let Some(Node::Element(elem)) = &child {
581 elem.mut_data(doc).parent = None;
582 }
583 child
584 }
585
586 pub fn clear_children(&self, doc: &mut Document) -> Vec<Node> {
588 let count = self.children(doc).len();
589 let mut removed = Vec::with_capacity(count);
590 for _ in 0..count {
591 let child = self.remove_child(doc, 0);
592 removed.push(child);
593 }
594 removed
595 }
596
597 pub fn detatch(&self, doc: &mut Document) -> Result<()> {
603 if self.is_container() {
604 return Err(Error::ContainerCannotMove);
605 }
606 let data = self.mut_data(doc);
607 if let Some(parent) = data.parent {
608 let pos = parent
609 .children(doc)
610 .iter()
611 .position(|n| n.as_element() == Some(*self))
612 .unwrap();
613 parent.remove_child(doc, pos);
614 }
615 Ok(())
616 }
617}
618
619#[cfg(test)]
620mod tests {
621 use super::{Document, Element, Node};
622
623 #[test]
624 fn test_children() {
625 let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
626 <outer>
627 inside outer
628 <middle>
629 <inner>
630 inside
631 </inner>
632 after inside
633 </middle>
634 <after>
635 inside after
636 </after>
637 </outer>
638 "#;
639 let doc = Document::parse_str(xml).unwrap();
640 let outer = doc.container().child_elements(&doc)[0];
641 let middle = outer.child_elements(&doc)[0];
642 let inner = middle.child_elements(&doc)[0];
643 let after = outer.child_elements(&doc)[1];
644 assert_eq!(doc.container().child_elements(&doc).len(), 1);
645 assert_eq!(outer.name(&doc), "outer");
646 assert_eq!(middle.name(&doc), "middle");
647 assert_eq!(inner.name(&doc), "inner");
648 assert_eq!(after.name(&doc), "after");
649 assert_eq!(outer.children(&doc).len(), 3);
650 assert_eq!(outer.child_elements(&doc).len(), 2);
651 assert_eq!(doc.container().children_recursive(&doc).len(), 8);
652 assert_eq!(
653 doc.container().child_elements_recursive(&doc),
654 vec![outer, middle, inner, after]
655 );
656 }
657
658 #[test]
659 fn test_namespace() {
660 let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
661 <root xmlns="ns", xmlns:p="pns">
662 <p:foo xmlns="inner">
663 Hello
664 </p:foo>
665 <p:bar xmlns:p="in2">
666 <c />
667 World!
668 </p:bar>
669 </root>"#;
670 let doc = Document::parse_str(xml).unwrap();
671 let container = doc.container().children(&doc)[0].as_element().unwrap();
672 let child_elements = container.child_elements(&doc);
673 let foo = *child_elements.get(0).unwrap();
674 let bar = *child_elements.get(1).unwrap();
675 let c = bar.child_elements(&doc)[0];
676 assert_eq!(c.prefix_name(&doc), ("", "c"));
677 assert_eq!(bar.full_name(&doc), "p:bar");
678 assert_eq!(bar.prefix(&doc), "p");
679 assert_eq!(bar.name(&doc), "bar");
680 assert_eq!(c.namespace(&doc).unwrap(), "ns");
681 assert_eq!(c.namespace_for_prefix(&doc, "p").unwrap(), "in2");
682 assert!(c.namespace_for_prefix(&doc, "random").is_none());
683 assert_eq!(bar.namespace(&doc).unwrap(), "in2");
684 assert_eq!(bar.namespace_for_prefix(&doc, "").unwrap(), "ns");
685 assert_eq!(foo.namespace(&doc).unwrap(), "pns");
686 assert_eq!(foo.namespace_for_prefix(&doc, "").unwrap(), "inner");
687 assert_eq!(foo.namespace_for_prefix(&doc, "p").unwrap(), "pns");
688 assert_eq!(container.namespace(&doc).unwrap(), "ns");
689 }
690
691 #[test]
692 fn test_find_text_content() {
693 let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
694 <core>
695 <p>Text</p>
696 <b>Text2</b>
697 </core>
698 "#;
699 let doc = Document::parse_str(xml).unwrap();
700 assert_eq!(
701 doc.root_element()
702 .unwrap()
703 .find(&doc, "p")
704 .unwrap()
705 .text_content(&doc),
706 "Text"
707 );
708 assert_eq!(
709 doc.root_element()
710 .unwrap()
711 .find(&doc, "b")
712 .unwrap()
713 .text_content(&doc),
714 "Text2"
715 );
716 assert_eq!(doc.root_element().unwrap().text_content(&doc), "TextText2")
717 }
718
719 #[test]
720 fn test_mutate_tree() {
721 let mut doc = Document::new();
723 let container = doc.container();
724 assert_eq!(container.parent(&doc), None);
725 assert_eq!(container.children(&doc).len(), 0);
726
727 let root = Element::build(&mut doc, "root").push_to(container);
729 assert_eq!(root.parent(&doc).unwrap(), container);
730 assert_eq!(doc.root_element().unwrap(), root);
731
732 let a = Element::new(&mut doc, "a");
734 assert_eq!(a.parent(&doc), None);
735
736 root.push_child(&mut doc, Node::Element(a)).unwrap();
738 assert_eq!(root.children(&doc)[0].as_element().unwrap(), a);
739 assert_eq!(a.parent(&doc).unwrap(), root);
740
741 let popped = root.pop_child(&mut doc).unwrap().as_element().unwrap();
743 assert_eq!(popped, a);
744 assert_eq!(root.children(&doc).len(), 0);
745 assert_eq!(a.parent(&doc), None);
746
747 let a = Element::new(&mut doc, "a");
749 a.push_to(&mut doc, root).unwrap();
750 assert_eq!(root.children(&doc)[0].as_element().unwrap(), a);
751 assert_eq!(a.parent(&doc).unwrap(), root);
752
753 root.remove_child(&mut doc, 0);
755 assert_eq!(root.children(&doc).len(), 0);
756 assert_eq!(a.parent(&doc), None);
757
758 let a = Element::new(&mut doc, "a");
760 root.insert_child(&mut doc, 0, Node::Element(a)).unwrap();
761 assert_eq!(root.children(&doc)[0].as_element().unwrap(), a);
762 assert_eq!(a.parent(&doc).unwrap(), root);
763
764 a.detatch(&mut doc).unwrap();
766 assert_eq!(root.children(&doc).len(), 0);
767 assert_eq!(a.parent(&doc), None);
768 }
769}