Struct roxmltree::Document

source ·
pub struct Document<'input> { /* private fields */ }
Expand description

An XML tree container.

A tree consists of Nodes. There are no separate structs for each node type. So you should check the current node type yourself via Node::node_type(). There are only 5 types: Root, Element, PI, Comment and Text.

As you can see there are no XML declaration and CDATA types. The XML declaration is basically skipped, since it doesn’t contain any valuable information (we support only UTF-8 anyway). And CDATA will be converted into a Text node as is, without any preprocessing (you can read more about it here).

Also, the Text node data can be accessed from the text node itself or from the parent element via Node::text() or Node::tail().

Implementations§

source§

impl<'input> Document<'input>

source

pub fn parse(text: &str) -> Result<Document<'_>, Error>

Parses the input XML string.

We do not support &[u8] or Reader because the input must be an already allocated UTF-8 string.

This is a shorthand for Document::parse_with_options(data, ParsingOptions::default()).

Examples
let doc = roxmltree::Document::parse("<e/>").unwrap();
assert_eq!(doc.descendants().count(), 2); // root node + `e` element node
source

pub fn parse_with_options( text: &str, opt: ParsingOptions ) -> Result<Document<'_>, Error>

Parses the input XML string using to selected options.

We do not support &[u8] or Reader because the input must be an already allocated UTF-8 string.

Examples
let opt = roxmltree::ParsingOptions::default();
let doc = roxmltree::Document::parse_with_options("<e/>", opt).unwrap();
assert_eq!(doc.descendants().count(), 2); // root node + `e` element node
Examples found in repository?
examples/ast.rs (line 15)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() != 2 {
        println!("Usage:\n\tcargo run --example ast -- input.xml");
        std::process::exit(1);
    }

    let text = std::fs::read_to_string(&args[1]).unwrap();

    let opt = roxmltree::ParsingOptions {
        allow_dtd: true,
        ..roxmltree::ParsingOptions::default()
    };
    match roxmltree::Document::parse_with_options(&text, opt) {
        Ok(doc) => print!("{:?}", doc),
        Err(e) => println!("Error: {}.", e),
    }
}
More examples
Hide additional examples
examples/print_pos.rs (line 15)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() != 2 {
        println!("Usage:\n\tcargo run --example print_pos -- input.xml");
        std::process::exit(1);
    }

    let text = std::fs::read_to_string(&args[1]).unwrap();
    let opt = roxmltree::ParsingOptions {
        allow_dtd: true,
        ..roxmltree::ParsingOptions::default()
    };
    let doc = match roxmltree::Document::parse_with_options(&text, opt) {
        Ok(doc) => doc,
        Err(e) => {
            println!("Error: {}.", e);
            return;
        }
    };

    // TODO: finish
    for node in doc.descendants() {
        if node.is_element() {
            println!(
                "{:?} at {}",
                node.tag_name(),
                doc.text_pos_at(node.range().start)
            );
        }
    }
}
examples/stats.rs (line 16)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() != 2 {
        println!("Usage:\n\tcargo run --example stats -- input.xml");
        std::process::exit(1);
    }

    let text = std::fs::read_to_string(&args[1]).unwrap();
    let opt = roxmltree::ParsingOptions {
        allow_dtd: true,
        ..roxmltree::ParsingOptions::default()
    };
    let doc = match roxmltree::Document::parse_with_options(&text, opt) {
        Ok(v) => v,
        Err(e) => {
            println!("Error: {}.", e);
            std::process::exit(1);
        }
    };

    println!(
        "Elements count: {}",
        doc.root().descendants().filter(|n| n.is_element()).count()
    );

    let attrs_count: usize = doc.root().descendants().map(|n| n.attributes().len()).sum();
    println!("Attributes count: {}", attrs_count);

    let ns_count: usize = doc.root().descendants().map(|n| n.namespaces().len()).sum();
    println!("Namespaces count: {}", ns_count);

    let mut uris = HashSet::new();
    for node in doc.root().descendants() {
        for ns in node.namespaces() {
            uris.insert((
                ns.name().unwrap_or("\"\"").to_string(),
                ns.uri().to_string(),
            ));
        }
    }
    println!("Unique namespaces count: {}", uris.len());
    if !uris.is_empty() {
        println!("Unique namespaces:");
        for (key, value) in uris {
            println!("  {:?}: {}", key, value);
        }
    }

    println!(
        "Comments count: {}",
        doc.root().descendants().filter(|n| n.is_comment()).count()
    );

    println!("Comments:");
    for node in doc.root().descendants().filter(|n| n.is_comment()) {
        println!("{:?}", node.text().unwrap());
    }
}
source§

impl<'input> Document<'input>

source

pub fn root<'a>(&'a self) -> Node<'a, 'input>

Returns the root node.

Examples
let doc = roxmltree::Document::parse("<e/>").unwrap();
assert!(doc.root().is_root());
assert!(doc.root().first_child().unwrap().has_tag_name("e"));
Examples found in repository?
examples/stats.rs (line 26)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() != 2 {
        println!("Usage:\n\tcargo run --example stats -- input.xml");
        std::process::exit(1);
    }

    let text = std::fs::read_to_string(&args[1]).unwrap();
    let opt = roxmltree::ParsingOptions {
        allow_dtd: true,
        ..roxmltree::ParsingOptions::default()
    };
    let doc = match roxmltree::Document::parse_with_options(&text, opt) {
        Ok(v) => v,
        Err(e) => {
            println!("Error: {}.", e);
            std::process::exit(1);
        }
    };

    println!(
        "Elements count: {}",
        doc.root().descendants().filter(|n| n.is_element()).count()
    );

    let attrs_count: usize = doc.root().descendants().map(|n| n.attributes().len()).sum();
    println!("Attributes count: {}", attrs_count);

    let ns_count: usize = doc.root().descendants().map(|n| n.namespaces().len()).sum();
    println!("Namespaces count: {}", ns_count);

    let mut uris = HashSet::new();
    for node in doc.root().descendants() {
        for ns in node.namespaces() {
            uris.insert((
                ns.name().unwrap_or("\"\"").to_string(),
                ns.uri().to_string(),
            ));
        }
    }
    println!("Unique namespaces count: {}", uris.len());
    if !uris.is_empty() {
        println!("Unique namespaces:");
        for (key, value) in uris {
            println!("  {:?}: {}", key, value);
        }
    }

    println!(
        "Comments count: {}",
        doc.root().descendants().filter(|n| n.is_comment()).count()
    );

    println!("Comments:");
    for node in doc.root().descendants().filter(|n| n.is_comment()) {
        println!("{:?}", node.text().unwrap());
    }
}
source

pub fn get_node<'a>(&'a self, id: NodeId) -> Option<Node<'a, 'input>>

Returns the node of the tree with the given NodeId.

Note: NodeId::new(0) represents the root node

Examples
let doc = roxmltree::Document::parse("\
<p>
    text
</p>
").unwrap();

use roxmltree::NodeId;
assert_eq!(doc.get_node(NodeId::new(0)).unwrap(), doc.root());
assert_eq!(doc.get_node(NodeId::new(1)), doc.descendants().find(|n| n.has_tag_name("p")));
assert_eq!(doc.get_node(NodeId::new(2)), doc.descendants().find(|n| n.is_text()));
assert_eq!(doc.get_node(NodeId::new(3)), None);
source

pub fn root_element<'a>(&'a self) -> Node<'a, 'input>

Returns the root element of the document.

Unlike root, will return a first element node.

The root element always exists.

Examples
let doc = roxmltree::Document::parse("<!-- comment --><e/>").unwrap();
assert!(doc.root_element().has_tag_name("e"));
source

pub fn descendants(&self) -> Descendants<'_, 'input>

Returns an iterator over document’s descendant nodes.

Shorthand for doc.root().descendants().

Examples found in repository?
examples/print_pos.rs (line 24)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() != 2 {
        println!("Usage:\n\tcargo run --example print_pos -- input.xml");
        std::process::exit(1);
    }

    let text = std::fs::read_to_string(&args[1]).unwrap();
    let opt = roxmltree::ParsingOptions {
        allow_dtd: true,
        ..roxmltree::ParsingOptions::default()
    };
    let doc = match roxmltree::Document::parse_with_options(&text, opt) {
        Ok(doc) => doc,
        Err(e) => {
            println!("Error: {}.", e);
            return;
        }
    };

    // TODO: finish
    for node in doc.descendants() {
        if node.is_element() {
            println!(
                "{:?} at {}",
                node.tag_name(),
                doc.text_pos_at(node.range().start)
            );
        }
    }
}
source

pub fn text_pos_at(&self, pos: usize) -> TextPos

Calculates TextPos in the original document from position in bytes.

Note: this operation is expensive.

Examples
use roxmltree::*;

let doc = Document::parse("\
<!-- comment -->
<e/>"
).unwrap();

assert_eq!(doc.text_pos_at(10), TextPos::new(1, 11));
assert_eq!(doc.text_pos_at(9999), TextPos::new(2, 5));
Examples found in repository?
examples/print_pos.rs (line 29)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() != 2 {
        println!("Usage:\n\tcargo run --example print_pos -- input.xml");
        std::process::exit(1);
    }

    let text = std::fs::read_to_string(&args[1]).unwrap();
    let opt = roxmltree::ParsingOptions {
        allow_dtd: true,
        ..roxmltree::ParsingOptions::default()
    };
    let doc = match roxmltree::Document::parse_with_options(&text, opt) {
        Ok(doc) => doc,
        Err(e) => {
            println!("Error: {}.", e);
            return;
        }
    };

    // TODO: finish
    for node in doc.descendants() {
        if node.is_element() {
            println!(
                "{:?} at {}",
                node.tag_name(),
                doc.text_pos_at(node.range().start)
            );
        }
    }
}
source

pub fn input_text(&self) -> &'input str

Returns the input text of the original document.

Examples
use roxmltree::*;

let doc = Document::parse("<e/>").unwrap();

assert_eq!(doc.input_text(), "<e/>");

Trait Implementations§

source§

impl<'input> Debug for Document<'input>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'input> RefUnwindSafe for Document<'input>

§

impl<'input> Send for Document<'input>

§

impl<'input> Sync for Document<'input>

§

impl<'input> Unpin for Document<'input>

§

impl<'input> UnwindSafe for Document<'input>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.