edit_xml/
element.rs

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>, // q:attr="val" => {"q:attr": "val"}
17    namespace_decls: HashMap<String, String>, // local namespace newly defined in attributes
18    parent: Option<Element>,
19    children: Vec<Node>,
20}
21/// Represents an XML element. It acts as a pointer to actual element data stored in Document.
22///
23/// This struct only contains a unique `usize` id and implements trait `Copy`.
24/// So you do not need to bother with having a reference.
25///
26/// Because the actual data of the element is stored in [`Document`],
27/// most methods takes `&Document` or `&mut Document` as its first argument.
28///
29/// Note that an element may only interact with elements of the same document,
30/// but the crate doesn't know which document an element is from.
31/// Trying to push an element from a different Document may result in unexpected errors.
32///
33/// # Examples
34///
35/// Find children nodes with attribute
36/// ```
37/// use edit_xml::{Document, Element};
38///
39/// let doc = Document::parse_str(r#"<?xml version="1.0"?>
40/// <data>
41///   <item class="value">a</item>
42///   <item class="value">b</item>
43///   <item></item>
44/// </data>
45/// "#).unwrap();
46///
47/// let data = doc.root_element().unwrap();
48/// let value_items: Vec<Element> = data.children(&doc)
49///     .iter()
50///     .filter_map(|node| node.as_element())
51///     .filter(|elem| elem.attribute(&doc, "class") == Some("value"))
52///     .collect();
53/// ```
54///
55#[derive(Debug, Clone, Copy, PartialEq)]
56pub struct Element {
57    id: usize,
58}
59
60impl Element {
61    /// Create a new empty element with `full_name`.
62    ///
63    /// If full_name contains `:`,
64    /// everything before that will be interpreted as a namespace prefix.
65    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    /// Create a new element with `full_name` and `text`.
69    ///
70    /// ```
71    /// use edit_xml::{Document, Element};
72    /// let mut doc = Document::new();
73    ///
74    /// let elem = Element::new_with_text(&mut doc, "name", "value");
75    /// assert_eq!(elem.text_content(&doc), "value");
76    /// ```
77    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    /// Chain methods to build an element easily.
84    /// The chain can be finished with `.finish()` or `.push_to(parent)`.
85    ///
86    /// # Example
87    /// ```
88    /// use edit_xml::{Document, Element, Node};
89    ///
90    /// let mut doc = Document::new();
91    ///
92    /// let elem = Element::build("root")
93    ///     .attribute("id", "main")
94    ///     .attribute("class", "main")
95    ///     .finish(&mut doc);
96    ///
97    /// doc.push_root_node(elem.as_node());
98    /// ```
99    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    /// Create a container Element
122    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    /// Returns `true` if element is a container.
129    ///
130    /// See [`Document::container()`] for more information on 'container'.
131    pub fn is_container(&self) -> bool {
132        self.id == 0
133    }
134
135    /// Equivalent to `Node::Element(self)`
136    #[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    /// Separate full_name by `:`, returning (prefix, name).
142    ///
143    /// The first str is `""` if `full_name` has no prefix.
144    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    /// Creates an [ElementDebug]
152    ///
153    /// Used to debug an element with its children.
154    pub fn debug<'element, 'doc>(
155        &'element self,
156        doc: &'doc Document,
157    ) -> ElementDebug<'element, 'doc> {
158        ElementDebug { element: self, doc }
159    }
160}
161
162/// Below are methods that take `&Document` as its first argument.
163impl 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    /// Returns true if this element is the root node of document.
173    ///
174    /// Note that this crate allows Document to have multiple elements, even though it's not valid xml.
175    pub fn is_root(&self, doc: &Document) -> bool {
176        self.parent(doc).map_or(false, |p| p.is_container())
177    }
178
179    /// Get full name of element, including its namespace prefix.
180    /// Use [`Element::name()`] to get its name without the prefix.
181    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    /// Get prefix and name of element. If it doesn't have prefix, will return an empty string.
190    ///
191    /// `<prefix: name` -> `("prefix", "name")`
192    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    /// Get namespace prefix of element, without name.
197    ///
198    /// `<prefix:name>` -> `"prefix"`
199    pub fn prefix<'a>(&self, doc: &'a Document) -> &'a str {
200        self.prefix_name(doc).0
201    }
202
203    /// Set prefix of element, preserving its name.
204    ///
205    /// `prefix` should not have a `:`,
206    /// or everything after `:` will be interpreted as part of element name.    
207    ///
208    /// If prefix is an empty string, removes prefix.
209    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    /// Get name of element, without its namespace prefix.
221    /// Use `Element::full_name()` to get its full name with prefix.
222    ///
223    /// `<prefix:name>` -> `"name"`
224    pub fn name<'a>(&self, doc: &'a Document) -> &'a str {
225        self.prefix_name(doc).1
226    }
227
228    /// Set name of element, preserving its prefix.
229    ///
230    /// `name` should not have a `:`,
231    /// or everything before `:` may be interpreted as namespace prefix.
232    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    /// Get attributes of element.
243    ///
244    /// The attribute names may have namespace prefix. To strip the prefix and only its name, call [`Element::separate_prefix_name`].
245    /// ```
246    /// use edit_xml::{Document, Element};
247    ///
248    /// let mut doc = Document::new();
249    /// let element = Element::build("name")
250    ///     .attribute("id", "name")
251    ///     .attribute("pre:name", "value")
252    ///     .finish(&mut doc);
253    ///
254    /// let attrs = element.attributes(&doc);
255    /// for (full_name, value) in attrs {
256    ///     let (prefix, name) = Element::separate_prefix_name(full_name);
257    ///     // ("", "id"), ("pre", "name")
258    /// }
259    /// ```
260    pub fn attributes<'a>(&self, doc: &'a Document) -> &'a HashMap<String, String> {
261        &self.data(doc).attributes
262    }
263
264    /// Get attribute value of an element by its full name. (Namespace prefix isn't stripped)
265    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    /// Add or set attribute.
270    ///
271    /// If `name` contains a `:`,
272    /// everything before `:` will be interpreted as namespace prefix.
273    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    /// Gets the namespace of this element.
286    ///
287    /// Shorthand for `self.namespace_for_prefix(doc, self.prefix(doc))`.
288    pub fn namespace<'a>(&self, doc: &'a Document) -> Option<&'a str> {
289        self.namespace_for_prefix(doc, self.prefix(doc))
290    }
291
292    /// Gets HashMap of `xmlns:prefix=namespace` declared in this element's attributes.
293    ///
294    /// Default namespace has empty string as key.
295    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    /// Get namespace value given prefix, for this element.
316    /// "xml" and "xmlns" returns its default namespace.
317    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    /// Concatenate all text content of this element, including its child elements `text_content()`.
340    ///
341    /// Implementation of [Node.textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
342    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    /// Clears all its children and inserts a [`Node::Text`] with given text.
349    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
356/// Below are methods related to finding nodes in tree.
357impl Element {
358    pub fn parent(&self, doc: &Document) -> Option<Element> {
359        self.data(doc).parent
360    }
361
362    /// `self.parent(doc).is_some()`
363    #[inline]
364    pub fn has_parent(&self, doc: &Document) -> bool {
365        self.parent(doc).is_some()
366    }
367
368    /// Get child [`Node`]s of this element.
369    pub fn children<'a>(&self, doc: &'a Document) -> &'a Vec<Node> {
370        &self.data(doc).children
371    }
372    /// Pushes all child nodes to `nodes`.
373    ///
374    /// This is used to recursively get all children of an element.
375    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    /// Get all child nodes recursively. (i.e. includes its children's children.)
387    #[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    /// `!self.children(doc).is_empty()`
395    #[inline]
396    pub fn has_children(&self, doc: &Document) -> bool {
397        !self.children(doc).is_empty()
398    }
399    /// Returns true if this element has children that are not empty text nodes.
400    ///
401    /// # Example
402    ///
403    /// ```
404    /// use edit_xml::{Document, Element};
405    /// let xml = r#"<?xml version="1.0"?>
406    /// <root>
407    ///    <empty></empty>
408    ///    <text>Hello</text>
409    /// </root>"#;
410    /// let doc = Document::parse_str(xml).unwrap();
411    /// let root = doc.root_element().unwrap();
412    /// let empty = root.find(&doc, "empty").unwrap();
413    /// let text = root.find(&doc, "text").unwrap();
414    /// assert!(!empty.has_children_ignore_whitespace(&doc));
415    /// assert!(text.has_children_ignore_whitespace(&doc));
416    /// ```
417    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    /// Get only child [`Element`]s of this element.
423    ///
424    /// This calls `.children().iter().filter_map().collect()`.
425    /// Use [`Element::children()`] if performance is important.
426    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    /// Get child [`Element`]s recursively. (i.e. includes its child element's child elements)
440    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    /// Find first direct child element with name `name`.
454    ///
455    ///
456    /// # Example
457    /// ```
458    /// use edit_xml::{Document, Element, ElementBuilder};
459    /// let mut doc = Document::new_with_root("root", |root| {
460    ///     root.create_element("child", |elem| {
461    ///        elem.add_text("Hello")
462    ///    })
463    /// });
464    ///
465    /// let root = doc.root_element().unwrap();
466    /// let child = root.find(&doc, "child");
467    /// assert!(child.is_some());
468    /// let child = child.unwrap();
469    /// assert_eq!(child.text_content(&doc), "Hello");
470    /// ```
471    ///
472    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    /// Find all direct child element with name `name`.
480    /// # Example
481    /// ```
482    /// use edit_xml::{Document, Element, ElementBuilder};
483    /// let mut doc = Document::new_with_root("root", |mut root| {
484    ///    for i in 0..3 {
485    ///        root = root.create_element("child", |elem| {
486    ///           elem.add_text(i.to_string())
487    ///       });
488    ///   }
489    ///   root
490    /// });
491    ///
492    /// let root = doc.root_element().unwrap();
493    /// let child = root.find_all(&doc, "child");
494    /// assert_eq!(child.len(), 3);
495    /// assert_eq!(child[0].text_content(&doc), "0");
496    /// assert_eq!(child[1].text_content(&doc), "1");
497    /// assert_eq!(child[2].text_content(&doc), "2");
498    /// ```
499    ///
500    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
509/// Below are functions that modify its tree-structure.
510///
511/// Because an element has reference to both its parent and its children,
512/// an element's parent and children is not directly exposed for modification.
513/// But in return, it is not possible for a document to be in an inconsistent state,
514/// where an element's parent doesn't have the element as its children.
515impl Element {
516    /// Equivalent to `vec.push()`.
517    ///
518    ///
519    /// # Errors
520    ///    - [EditXMLError::HasAParent]: When you want to replace an element's parent with another,
521    ///         call `element.detach()` to make it parentless first.
522    ///         This is to make it explicit that you are changing an element's parent, not adding another.
523    ///    - [EditXMLError::ContainerCannotMove]: The container element's parent must always be None.
524    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    /// Creates a new child element with `name` and pushes it to this element.
545    ///
546    /// # Example
547    /// ```
548    /// use edit_xml::{Document, Element, ElementBuilder};
549    /// let mut doc = Document::new();
550    /// let root = ElementBuilder::new("root").finish(&mut doc);
551    /// root.create_child(&mut doc, "child", |elem| {
552    ///    elem.add_text("Hello")
553    /// });
554    /// let child = root.find(&doc, "child").unwrap();
555    /// let children_of_the_child = child.children(&doc);
556    /// assert_eq!(children_of_the_child.len(), 1);
557    /// assert_eq!(children_of_the_child[0].text_content(&doc), "Hello");
558    /// ```
559    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    /// Equivalent to `vec.insert()`.
569    ///
570    /// # Panics
571    ///
572    /// Panics if `index > self.children().len()`
573    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    /// Equivalent to `vec.remove()`.
589    ///
590    /// # Panics
591    ///
592    /// Panics if `index >= self.children().len()`.
593    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    /// Equivalent to `vec.pop()`.
602    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    /// Remove all children and return them.
611    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    /// Removes itself from its parent. Note that you can't attach this element to other documents.
622    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        // OG Test had         <root xmlns="ns", xmlns:p="pns">
681
682        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        // Test tree consistency after mutating tree
744        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        // Element::build.push_to
750        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        // Element::new
755        let a = Element::new(&mut doc, "a");
756        assert_eq!(a.parent(&doc), None);
757
758        // Element.push_child
759        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        // Element.pop
764        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        // Element.push_child
770        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        // Element.remove_child
775        root.remove_child(&mut doc, 0);
776        assert_eq!(root.children(&doc).len(), 0);
777        assert_eq!(a.parent(&doc), None);
778
779        // Element.insert_child
780        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        // Element.detach
786        a.detach(&mut doc).unwrap();
787        assert_eq!(root.children(&doc).len(), 0);
788        assert_eq!(a.parent(&doc), None);
789        Ok(())
790    }
791}