#xml #dom #sax #x-path #x-path3

bin+lib amxml

XML processor with some features of XPath 2.0 / 3.0 / 3.1

7 releases

Uses old Rust 2015

0.5.3 Sep 18, 2018
0.5.2 Aug 7, 2018
0.5.1 Jul 26, 2018
0.4.9 Jul 3, 2018
0.4.8 Jun 25, 2018

#451 in Web programming

Download history 44/week @ 2023-02-03 82/week @ 2023-02-10 69/week @ 2023-02-17 61/week @ 2023-02-24 57/week @ 2023-03-03 97/week @ 2023-03-10 118/week @ 2023-03-17 112/week @ 2023-03-24 54/week @ 2023-03-31 113/week @ 2023-04-07 45/week @ 2023-04-14 42/week @ 2023-04-21 110/week @ 2023-04-28 67/week @ 2023-05-05 79/week @ 2023-05-12 49/week @ 2023-05-19

305 downloads per month
Used in 2 crates (via freedesktop-categories-codegen)


11K SLoC


Rust XML processor with some features of XPath 2.0 / 3.0 / 3.1.

Building DOM tree from XML document string

Building DOM tree can be done by calling new_document() function. The DOM tree can be turned into String.

use amxml::dom::*;
let xml_string = r#"<?xml version="1.0"?><article>foo</article>"#;
let doc = new_document(&xml_string).unwrap();
let result = doc.to_string();
assert_eq!(result, xml_string);

Navigating DOM tree

Navigating DOM tree, or retrieving the DOM node, can be done by root_element(), parent(), first_child(), nth_child(), attribute_value() methods.

See the description and example of corresponding method.

Retrieving the DOM node by XPath

But more convenient way for retrieving the DOM node is, perhaps, using XPath, especially when the search criteria is not trivial.

First XPath example is somewhat straightforward. each_node() method visits the DOM nodes that match with the given XPath, and apply the function (closure) to these nodes.

use amxml::dom::*;
let xml = r#"<root><a img="a1"/><a img="a2"/></root>"#;
let doc = new_document(xml).unwrap();
let mut img = String::new();
doc.each_node("/root/a", |n| {
    img += n.attribute_value("img").unwrap().as_str();
assert_eq!(img, "a1a2");

Second XPath example is more complex. This finds the clerk OR engineer (NOT advisor) who has no subordinates. Note that clerks and enginners appear in document order in each_node() iteration.

use amxml::dom::*;
let xml = r#"
    <clerk name="Ann">
        <advisor name="Betty"/>
        <clerk name="Charlie"/>
    <engineer name="Dick">
        <engineer name="Emily"/>
    <clerk name="Fred"/>
let doc = new_document(xml).unwrap();
let root = doc.root_element();
let xpath = "(//clerk | //engineer)[count(./*) = 0]";
let mut names = String::new();
root.each_node(xpath, |n| {
    names += n.attribute_value("name").unwrap().as_str();
    names += "; ";
assert_eq!(names, "Charlie; Emily; Fred; ");

Also see the description and example of each_node(), get_first_node(), get_nodeset() methods.

Evaluating XPath

XPath can also be used to evaluate for the DOM tree and get boolean, numeric, string values as well as DOM node. The example below lists up the students, and whether or not each student got 80 or more points in every (not some) examination.

use amxml::dom::*;
let xml = r#"
        <exam subject="math" point="70"/>
        <exam subject="science" point="90"/>
        <exam subject="math" point="80"/>
        <exam subject="science" point="95"/>
        <exam subject="math" point="60"/>
        <exam subject="science" point="75"/>
let doc = new_document(xml).unwrap();
let root = doc.root_element();
let xpath= r#"
for $student in /root/student return
     every $exam in $student/exam satisfies number($exam/@point) >= 80)
let result = root.eval_xpath(xpath).unwrap();
assert_eq!(result.to_string(), "(George, false, Harry, true, Ivonne, false)");

Manipurating the DOM node

Inserting / replacing / deleting the DOM node can be done by methods like append_child(), insert_as_previous_sibling(), insert_as_next_sibling(), delete_child(), replace_with(), set_attribute(), delete_attribute() methods.

See the description and example of corresponding method.

No runtime deps