extern crate earleybird;
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::rc::Rc;
use url::Url;
use qualname::{NcName, QName};
use xrust::item::{Item, Node, SequenceTrait};
use xrust::parser::ParseError;
use xrust::parser::xml::parse;
use xrust::transform::context::StaticContextBuilder;
use xrust::trees::smite::RNode;
use xrust::value::Value;
use xrust::xdmerror::{Error, ErrorKind};
use xrust::xslt::from_document;
use earleybird::ixml_grammar::{ixml_grammar, ixml_tree_to_grammar};
use earleybird::parser::{Content, Parser};
use indextree::{Arena, NodeId};
fn to_rnode(arena: &Arena<Content>) -> RNode {
let t = RNode::new_document();
let root = arena.iter().next().unwrap();
let root_id = arena.get_node_id(root).unwrap();
for child in root_id.children(arena) {
to_rnode_aux(arena, child, t.clone())
}
t
}
fn to_rnode_aux(arena: &Arena<Content>, n: NodeId, mut t: RNode) {
if let Some(m) = arena.get(n) {
match m.get() {
Content::Root => {
for child in n.children(arena) {
to_rnode_aux(arena, child, t.clone())
}
}
Content::Element(name) => {
let new = t
.new_element(QName::from_local_name(
NcName::try_from(name.as_str()).unwrap(),
))
.expect("unable to create element node");
t.push(new.clone()).expect("unable to append node");
for attr in n
.children(arena)
.filter(|a| arena.get(*a).unwrap().get().is_attr())
{
if let Content::Attribute(attr_name, attr_value) =
arena.get(attr).unwrap().get()
{
let new_attr = t
.new_attribute(
QName::from_local_name(
NcName::try_from(attr_name.as_str()).unwrap(),
),
Rc::new(Value::from(attr_value.clone())),
)
.expect("unable to create attribute node");
t.add_attribute(new_attr).expect("unable to append node");
}
}
for child in n.children(arena) {
to_rnode_aux(arena, child, new.clone())
}
}
Content::Attribute(name, value) => {
let new = t
.new_attribute(
QName::from_local_name(NcName::try_from(name.as_str()).unwrap()),
Rc::new(Value::from(value.clone())),
)
.expect("unable to create attribute node");
t.add_attribute(new).expect("unable to append node");
}
Content::Text(value) => {
let new = t
.new_text(Rc::new(Value::from(value.clone())))
.expect("unable to create text node");
t.push(new).expect("unable to append node");
}
}
}
}
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Usage: {} stylesheet source", args[0]);
return;
}
let stylepath = Path::new(&args[1]);
let mut stylefile = match File::open(&stylepath) {
Err(why) => {
panic!(
"unable to open stylesheet \"{}\" due to \"{}\"",
&args[1], why
)
}
Ok(f) => f,
};
let mut stylexml = String::new();
match stylefile.read_to_string(&mut stylexml) {
Err(why) => panic!("unable to read from \"{}\" due to \"{}\"", &args[1], why),
Ok(_) => {}
};
let style = RNode::new_document();
parse(
style.clone(),
stylexml.trim(),
Some(|_: &_| Err(ParseError::MissingNameSpace)),
)
.expect("failed to parse XSL stylesheet");
let srcpath = Path::new(&args[2]);
let mut srcfile = match File::open(&srcpath) {
Err(why) => {
panic!(
"unable to open source document \"{}\" due to \"{}\"",
&args[2], why
)
}
Ok(f) => f,
};
let mut srcmd = String::new();
match srcfile.read_to_string(&mut srcmd) {
Err(why) => panic!("unable to read from \"{}\" due to \"{}\"", &args[2], why),
Ok(_) => {}
};
let g = ixml_grammar();
let ixml = r###"doc = para+.
para = letter+, eol?.
eol = "X".
-letter = " "|"a"|"b"|"c"|"A"|"B"|"C"."###;
let mut parser = Parser::new(g);
let arena = parser.parse(ixml).expect("unable to parse grammar");
let gen_grammar = ixml_tree_to_grammar(&arena);
let mut gen_parser = Parser::new(gen_grammar);
let md_arena = gen_parser
.parse("BaC caaa B bAcXabcX")
.expect("unable to parse input");
let md = to_rnode(&md_arena);
let pwd = std::env::current_dir().expect("unable to get current directory");
let pwds = pwd
.into_os_string()
.into_string()
.expect("unable to convert pwd");
let mut ctxt = from_document(
style,
Some(
Url::parse(format!("file://{}/{}", pwds, &args[1]).as_str())
.expect("unable to parse stylesheet URL"),
),
|_| {
Err(Error::new(
ErrorKind::Unknown,
String::from("loading resources not implemented"),
))
},
|_| {
Err(Error::new(
ErrorKind::Unknown,
String::from("loading external resources not implemented"),
))
},
)
.expect("failed to compile XSL stylesheet");
ctxt.context(vec![Item::Node(md)], 0);
ctxt.result_document(RNode::new_document());
let mut stctxt = StaticContextBuilder::new()
.message(|_| Ok(()))
.fetcher(|_| Err(Error::new(ErrorKind::NotImplemented, "not implemented")))
.parser(|_| Err(Error::new(ErrorKind::NotImplemented, "not implemented")))
.build();
let resultdoc = ctxt
.evaluate(&mut stctxt)
.expect("failed to evaluate stylesheet");
println!("{}", resultdoc.to_xml());
}