Add xml open support

This commit is contained in:
Jonathan Turner
2019-06-11 18:26:03 +12:00
parent 3f3ea4153a
commit 7642541755
11 changed files with 142 additions and 0 deletions

View File

@ -56,6 +56,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
command("size", size::size),
command("from-json", from_json::from_json),
command("from-toml", from_toml::from_toml),
command("from-xml", from_xml::from_xml),
command("from-yaml", from_yaml::from_yaml),
command("get", get::get),
command("open", open::open),

View File

@ -8,6 +8,7 @@ crate mod config;
crate mod first;
crate mod from_json;
crate mod from_toml;
crate mod from_xml;
crate mod from_yaml;
crate mod get;
crate mod ls;

68
src/commands/from_xml.rs Normal file
View File

@ -0,0 +1,68 @@
use crate::object::{DataDescriptor, Dictionary, Primitive, Value};
use crate::prelude::*;
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
if n.is_element() {
let name = n.tag_name().name().trim().to_string();
let mut children_values = vec![];
for c in n.children() {
children_values.push(from_node_to_value(&c));
}
let children_values: Vec<Value> = children_values
.into_iter()
.filter(|x| match x {
Value::Primitive(Primitive::String(f)) => {
if f.trim() == "" {
false
} else {
true
}
}
_ => true,
})
.collect();
let mut collected = Dictionary::default();
collected.add(
DataDescriptor::from(name.clone()),
Value::List(children_values),
);
Value::Object(collected)
} else if n.is_comment() {
Value::Primitive(Primitive::String("<comment>".to_string()))
} else if n.is_pi() {
Value::Primitive(Primitive::String("<processing_instruction>".to_string()))
} else if n.is_text() {
Value::Primitive(Primitive::String(n.text().unwrap().to_string()))
} else {
Value::Primitive(Primitive::String("<unknown>".to_string()))
}
}
fn from_document_to_value(d: &roxmltree::Document) -> Value {
from_node_to_value(&d.root_element())
}
pub fn from_xml_string_to_value(s: String) -> Value {
match roxmltree::Document::parse(&s) {
Ok(doc) => from_document_to_value(&doc),
Err(_) => Value::Error(Box::new(ShellError::string(
"Can't convert string from xml".to_string(),
))),
}
}
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
let out = args.input;
Ok(out
.map(|a| match a {
Value::Primitive(Primitive::String(s)) => ReturnValue::Value(from_xml_string_to_value(s)),
_ => ReturnValue::Value(Value::Error(Box::new(ShellError::string(
"Trying to convert XML from non-string".to_string(),
)))),
})
.boxed())
}

View File

@ -32,6 +32,18 @@ pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
}
}
let amount = args.positional[0].as_i64();
// If it's a number, get the row instead of the column
if let Ok(amount) = amount {
return Ok(args
.input
.skip(amount as u64)
.take(1)
.map(|v| ReturnValue::Value(v))
.boxed());
}
let fields: Result<Vec<String>, _> = args.positional.iter().map(|a| a.as_string()).collect();
let fields = fields?;

View File

@ -103,6 +103,11 @@ pub fn open(args: CommandArgs) -> Result<OutputStream, ShellError> {
crate::commands::from_json::from_json_string_to_value(contents),
));
}
Some(x) if x == "xml" && !open_raw => {
stream.push_back(ReturnValue::Value(
crate::commands::from_xml::from_xml_string_to_value(contents),
));
}
Some(x) if x == "yml" && !open_raw => {
stream.push_back(ReturnValue::Value(
crate::commands::from_yaml::from_yaml_string_to_value(contents),

View File

@ -183,6 +183,18 @@ impl Value {
crate fn get_data_by_key(&'a self, name: &str) -> Option<&Value> {
match self {
Value::Object(o) => o.get_data_by_key(name),
Value::List(l) => {
for item in l {
match item {
Value::Object(o) => match o.get_data_by_key(name) {
Some(v) => return Some(v),
None => {}
}
_ => {}
}
}
None
}
_ => None,
}
}