Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xdoc: make element struct members private #74

Merged
merged 6 commits into from
Nov 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

Currently we are using v0.0.x where every version can and will contain breaking changes.

## [Unreleased]
## Added
- Nothing yet.

### Changed
- Make `Element` struct members private [#74]

[#74]: https://github.com/webern/exile/pull/74

## [v0.0.2] - 2020-11-15
### Added
- Support for single-quoted attributes [#58]
- `exile::load` for loading files [#58]
- A lot of work on generating test cases with Java [#67], [#70], [#72]


### Changed
- The `xdoc` `Version` and `Encoding` enums were weird, changed to remove `None` [#59]
- Added some mutating functions to `Document`, `Element`, and maybe others
Expand Down Expand Up @@ -53,7 +61,7 @@ Currently we are using v0.0.x where every version can and will contain breaking
[#52]: https://github.com/webern/exile/pull/52

<!-- version diff links -->
[Unreleased]: https://github.com/webern/exile/compare/v0.0.1...HEAD
[Unreleased]: https://github.com/webern/exile/compare/v0.0.2...HEAD
[v0.0.2]: https://github.com/webern/exile/compare/v0.0.1...v0.0.2
[v0.0.1]: https://github.com/webern/exile/compare/v0.0.0...v0.0.1
[v0.0.0]: https://github.com/webern/exile/releases/tag/v0.0.0
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "Nacent XML DOM Library"
authors = ["Matthew James Briggs <matthew.james.briggs@gmail.com>"]
categories = ["encoding", "parser-implementations", "parsing"]
edition = "2018"
exclude = ["tests/"]
exclude = ["bin/", "data/", "target/", "testgen/", "tests/"]
keywords = ["xml"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ let xml = r#"

let doc = exile::parse(xml).unwrap();
for child in doc.root().children() {
println!("element name: {}", child.name);
if let Some(attribute) = child.attributes.map().get("name") {
println!("element name: {}", child.name());
if let Some(attribute) = child.attribute("name") {
println!("name attribute: {}", attribute);
}
}
Expand All @@ -50,19 +50,18 @@ Authoring XML looks like this.
```rust
use exile::{Document, Element, Node};
let mut root = Element::from_name("my_root");
// TODO - improve the interface
root.attributes.mut_map().insert("foo".into(), "bar".into());
root.add_attribute("foo", "bar");
let mut child = Element::from_name("my_child");
child.nodes.push(Node::Text("Hello World!".into()));
root.nodes.push(Node::Element(child));
child.add_text("Hello World!");
root.add_child(child);
let doc = Document::from_root(root);
println!("{}", doc.to_string());
```

The program above prints:
The above program prints:

```xml
<my_root foo="bar">
<my_child>Hello World!</my_child>
</my_root>
```
```
17 changes: 17 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use core::fmt;
use std::fmt::{Display, Formatter};

use crate::parser::ParserState;
use crate::xdoc::error::XDocErr;

////////////////////////////////////////////////////////////////////////////////////////////////////
// public error type
Expand All @@ -19,6 +20,8 @@ pub type Result<T> = std::result::Result<T, Error>;
pub enum Error {
/// A syntax error encountered when parsing an XML document.
Parse(ParseError),
/// An error related to the `Document` model.
XdocErr(XDocErr),
/// Any other error not related to the syntax of the XML document.
Other(OtherError),
}
Expand All @@ -27,6 +30,7 @@ impl Display for crate::error::Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Error::Parse(pe) => pe.fmt(f),
Error::XdocErr(xe) => xe.fmt(f),
Error::Other(oe) => oe.fmt(f),
}
}
Expand All @@ -42,6 +46,13 @@ impl std::error::Error for crate::error::Error {
None
}
}
Error::XdocErr(e) => {
if let Some(s) = &e.source {
Some(s.as_ref())
} else {
None
}
}
Error::Other(e) => {
if let Some(s) = &e.source {
Some(s.as_ref())
Expand All @@ -53,6 +64,12 @@ impl std::error::Error for crate::error::Error {
}
}

impl From<XDocErr> for Error {
fn from(xe: XDocErr) -> Self {
Error::XdocErr(xe)
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// public error data
////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
26 changes: 13 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ let xml = r#"

let doc = exile::parse(xml).unwrap();
for child in doc.root().children() {
println!("element name: {}", child.name);
if let Some(attribute) = child.attributes.map().get("name") {
println!("element name: {}", child.name());
if let Some(attribute) = child.attribute("name") {
println!("name attribute: {}", attribute);
}
}
Expand All @@ -47,22 +47,22 @@ Authoring XML looks like this.
```
use exile::{Document, Element, Node};
let mut root = Element::from_name("my_root");
// TODO - improve the interface
root.attributes.mut_map().insert("foo".into(), "bar".into());
root.add_attribute("foo", "bar");
let mut child = Element::from_name("my_child");
child.nodes.push(Node::Text("Hello World!".into()));
root.nodes.push(Node::Element(child));
child.add_text("Hello World!");
root.add_child(child);
let doc = Document::from_root(root);
println!("{}", doc.to_string());
```

The program above prints:
The above program prints:

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

*/

#![deny(rust_2018_idioms)]
Expand Down Expand Up @@ -101,13 +101,13 @@ fn simple_document_test() {
"#;
let doc = parse(xml).unwrap();
let root = doc.root();
assert_eq!("r", root.name.as_str());
assert_eq!(1, root.nodes.len());
let child = root.nodes.first().unwrap();
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.as_str());
let attribute_value = element.attributes.map().get("b").unwrap();
assert_eq!("c", attribute_value.as_str());
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")
}
Expand Down
28 changes: 11 additions & 17 deletions src/parser/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::parser::chars::is_name_start_char;
use crate::parser::pi::parse_pi;
use crate::parser::string::{parse_string, StringType};
use crate::parser::{parse_name, skip_comment, Iter};
use crate::xdoc::OrdMap;
use crate::{Element, Misc, Node};

pub(crate) fn parse_element(iter: &mut Iter<'_>) -> Result<Element> {
Expand All @@ -24,7 +23,7 @@ pub(crate) fn parse_element(iter: &mut Iter<'_>) -> Result<Element> {

// now the only valid chars are '>' or the start of an attribute name
if iter.is_name_start_char() {
element.attributes = parse_attributes(iter)?;
parse_attributes(iter, &mut element)?;
}

// check and return early if it is an empty, self-closing tag that had attributes
Expand Down Expand Up @@ -55,19 +54,14 @@ fn split_element_name(input: &str) -> Result<(&str, &str)> {

fn make_named_element(input: &str) -> Result<Element> {
let split = split_element_name(input)?;
Ok(Element {
namespace: match split.0 {
"" => None,
_ => Some(split.0.to_owned()),
},
name: split.1.to_string(),
attributes: Default::default(),
nodes: vec![],
})
let mut element = Element::from_name(split.1);
if !split.0.is_empty() {
element.set_prefix(split.0)?
}
Ok(element)
}

fn parse_attributes(iter: &mut Iter<'_>) -> Result<OrdMap> {
let mut attributes = OrdMap::new();
fn parse_attributes(iter: &mut Iter<'_>, element: &mut Element) -> Result<()> {
loop {
iter.skip_whitespace()?;
if iter.is('/') || iter.is('>') {
Expand All @@ -86,12 +80,12 @@ fn parse_attributes(iter: &mut Iter<'_>) -> Result<OrdMap> {
iter.advance_or_die()?;
let value = parse_attribute_value(iter, string_type)?;
expect!(iter, start)?;
attributes.mut_map().insert(key, value);
element.add_attribute(key, value);
if !iter.advance() {
break;
}
}
Ok(attributes)
Ok(())
}

fn attribute_start_quote(iter: &Iter<'_>) -> Result<(char, StringType)> {
Expand Down Expand Up @@ -136,12 +130,12 @@ fn parse_children(iter: &mut Iter<'_>, parent: &mut Element) -> Result<()> {
// do nothing
}
LTParse::Some(node) => {
parent.nodes.push(node);
parent.add_node(node);
}
}
} else {
let text = parse_text(iter)?;
parent.nodes.push(Node::Text(text));
parent.add_node(Node::Text(text));
}
// some parsing functions may return with the iter pointing to the last thing that was part
// of their construct, while others might advance the iter to the next char *after* the
Expand Down
Loading