1
  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
 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
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*!
![build](https://github.com/webern/exile/workflows/exile%20ci/badge.svg)

`exile` is a Rust library for reading and writing XML.

The goal, at least initially, is to provide an abstract syntax tree of an XML file.
As such, this is a Exile is a dom parser and loads the complete contents of the document into memory.

Currently supported:
- Attributes
- CDATA Sections
- Comment Parsing
- Elements
- Processing Instructions
- Text Nodes
- UTF-8
- Whitespace Normalization

Not Supported:
- Doctypes
- Entities
- Entity References
- Other Encodings
- Whitesace Preservation: All text nodes are treated as if whitespace `collapse` were in-effect.

# Example

Parsing XML looks like this.

```
let xml = r#"
<root>
  <thing name="foo"/>
  <thing>bar</thing>
</root>
"#;

let doc = exile::parse(xml).unwrap();
for child in doc.root().children() {
    println!("element name: {}", child.name());
    if let Some(attribute) = child.attribute("name") {
        println!("name attribute: {}", attribute);
    }
}
```

Authoring XML looks like this.

```
use exile::{Document, Element, Node};
let mut root = Element::from_name("my_root");
root.add_attribute("foo", "bar");
let mut child = Element::from_name("my_child");
child.add_text("Hello World!");
root.add_child(child);
let doc = Document::from_root(root);
println!("{}", doc.to_string());
```

The above program prints:

```xml
<my_root foo="bar">
  <my_child>Hello World!</my_child>
</my_root>
```

*/

#![deny(rust_2018_idioms)]
#![deny(missing_docs, unused_imports)]

use std::path::Path;

pub use crate::parser::ParseError;
pub use crate::xdoc::{
    Declaration, Document, Element, Encoding, Misc, Node, Version, WriteOpts, PI,
};
pub use crate::xmlns::{Namespace, NcName, NsErr, QName};

/// The `error` module defines the error types for this library.
#[macro_use]
mod macros;
mod constants;
pub mod error;
pub mod parser;
mod xdoc;
mod xmlns;

/// Parse an XML file held in string contents.
pub fn parse<S: AsRef<str>>(xml: S) -> crate::error::Result<Document> {
    parser::document_from_string(xml)
}

/// Load a document from a file.
pub fn load<P: AsRef<Path>>(path: P) -> crate::error::Result<Document> {
    parser::document_from_file(path)
}

// TODO - streaming https://github.com/webern/exile/issues/20

#[test]
fn simple_document_test() {
    let xml = r#"
    <r>
      <a b="c"/>
    </r>
    "#;
    let doc = parse(xml).unwrap();
    let root = doc.root();
    assert_eq!("r", root.name());
    assert_eq!(1, root.nodes_len());
    let child = root.first_node().unwrap();
    if let Node::Element(element) = child {
        assert_eq!("a", element.name());
        let attribute_value = element.attribute("b").unwrap();
        assert_eq!("c", attribute_value);
    } else {
        panic!("expected element but found a different type of node")
    }
}