use crate::item::{Item, Document, Node};
use crate::xdmerror::*;
use roxmltree::{Document as RoxDoc, Node as RoxNode};
impl<'a> Document for RoxDoc<'a> {
fn to_string(&self) -> String {
self.root().to_string()
}
fn to_xml(&self) -> String {
self.root().to_xml()
}
fn to_json(&self) -> String {
self.root().to_json()
}
fn children(&self) -> Vec<Box<dyn Node>> {
vec![Box::new(self.root_element())]
}
fn get_root_element(&self) -> Option<Box<dyn Node>> {
Some(Box::new(self.root_element()))
}
fn to_int(&self) -> Result<i64, Error> {
self.get_root_element().to_int()
}
fn to_double(&self) -> f64 {
f64::NAN
}
}
impl<'a, 'input> Node for RoxNode<'a, 'input> {
fn to_name(&self) -> String {
self.tag_name().name()
}
fn to_string(&self) -> String {
match self.node_type() {
roxmltree::NodeType::Root => {
if self.has_children() {
self.first_child().to_string()
} else {
String::new()
}
}
roxmltree::NodeType::Element => {
if self.has_children() {
self
.children()
.fold(String::new(), |s,c| s + xnode_sv_helper(c).as_str())
} else {
"".to_string()
}
}
roxmltree::NodeType::Text => {
self.text().unwrap_or("").to_string()
}
roxmltree::NodeType::Comment => {
self.text().unwrap_or("").to_string()
}
roxmltree::NodeType::PI => {
self.text().unwrap_or("").to_string()
}
}
}
fn to_xml(&self) -> String {
match self.node_type() {
roxmltree::NodeType::Root => {
if self.has_children() {
self.first_child().unwrap().to_xml()
} else {
String::new()
}
}
roxmltree::NodeType::Element => {
if self.has_children() {
format!("<{}>{}</{}>", self.tag_name().name(), self.children().fold(String::new(), |s,c| s + c.to_xml()), self.tag_name().name())
} else {
format!("<{}/>", self.tag_name().name())
}
}
roxmltree::NodeType::Text => {
String::from(self.text().unwrap_or(""))
}
roxmltree::NodeType::Comment => {
let mut r = String::new();
r.push_str("<!--");
r.push_str(self.text().unwrap_or(""));
r.push_str("-->");
r
}
roxmltree::NodeType::PI => {
let mut r = String::new();
r.push_str("<?");
r.push_str(self.tag_name().name());
r.push_str(" ");
r.push_str(self.text().unwrap_or(""));
r.push_str("?>");
r
}
}
}
fn to_json(&self) -> String {
match self.node_type() {
roxmltree::NodeType::Root => {
if self.has_children() {
self.first_child().unwrap().to_json()
} else {
"{}".to_string()
}
}
roxmltree::NodeType::Element => {
if self.has_children() {
format!("\"{}\": {}", self.tag_name().name(), self.children().fold(String::new(), |s,c| s + c.to_json()))
} else {
format!("\"{}\": \"\"", self.tag_name().name())
}
}
roxmltree::NodeType::Text => {
format!("\"{}\"", String::from(self.text().unwrap_or("")))
}
roxmltree::NodeType::Comment |
roxmltree::NodeType::PI => {
"".to_string()
}
}
}
fn doc(&self) -> Option<Box<dyn Document>> {
None
}
fn parent(&self) -> Option<Box<dyn Node>> {
match self.parent() {
Some(p) => Some(Box::new(p)),
None => None,
}
}
fn children(&self) -> Vec<Box<dyn Node>> {
let mut ret: Vec<Box<dyn Node>> = Vec::new();
for c in self.children() {
ret.push(Box::new(c));
}
ret
}
fn to_int(&self) -> Result<i64, Error> {
match self.to_string().parse::<i64>() {
Ok(i) => Ok(i),
Result::Err(e) => Result::Err(Error{kind: ErrorKind::Unknown, message: e.to_string()}),
}
}
fn to_double(&self) -> f64 {
match self.to_string().parse::<f64>() {
Ok(f) => f,
Result::Err(_) => f64::NAN
}
}
fn is_element(&self) -> bool {
self.is_element()
}
}
fn xnode_sv_helper(c: RoxNode) -> String {
let mut s: String = String::new();
for e in c.descendants()
.filter(|d| d.node_type() == roxmltree::NodeType::Text) {
s.push_str(e.text().unwrap_or(""));
}
s
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn node_stringvalue_1() {
let d = roxmltree::Document::parse("<Test><Level2>test text</Level2></Test>").expect("unable to parse XML");
let i = Item::Node(&d.root().first_child().unwrap().first_child().unwrap());
assert_eq!(i.to_string(), "test text")
}
#[test]
fn node_stringvalue_2() {
let d = roxmltree::Document::parse("<Test><Level2>test</Level2><Level3>text</Level3></Test>").expect("unable to parse XML");
let i = Item::Node(&d.root().first_child().unwrap());
assert_eq!(i.to_string(), "testtext")
}
#[test]
fn xnode_doc() {
let d = roxmltree::Document::parse("<Test/>").expect("unable to parse XML");
let i = Item::Document(&d);
assert_eq!(i.to_xml(), "<Test/>")
}
#[test]
fn node_xml() {
let d = roxmltree::Document::parse("<Test><Level2>test text</Level2></Test>").expect("unable to parse XML");
let i = Item::Node(&d.root().first_child().unwrap().first_child().unwrap());
assert_eq!(i.to_string(), "test text");
assert_eq!(i.to_xml(), "<Level2>test text</Level2>")
}
}