KWARC / rust-libxml

Rust wrapper for libxml2
https://crates.io/crates/libxml
MIT License
76 stars 38 forks source link

Nokogiri like api #21

Closed triptec closed 6 years ago

triptec commented 7 years ago

I've been playing around with a Nokogiri like api, would we like something like this?

#![allow(non_snake_case)]
use tree::Document;
/// XML parsing module
pub mod xml;

use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;

pub trait XmlInput {
    const IS_PATH: bool = false;
    fn is_path(&self) -> bool { Self::IS_PATH }
    fn data(&self) -> String;
}

impl XmlInput for str {
    fn data(&self) -> String {
        String::from(self)
    }
}

impl XmlInput for String {
    fn data(&self) -> String {
        self.to_owned()
    }
}

impl XmlInput for Path {
    const IS_PATH: bool = true;
    fn data(&self) -> String {
        String::from(self.to_str().expect("Could not get path"))
    }
}

impl XmlInput for File {
    const IS_PATH: bool = false;
    fn data(&self) -> String {
        let mut tmp = String::new();
        {
            let mut a = BufReader::new(self);
            a.read_to_string(&mut tmp).expect("Could not read_to_string");
        }
        tmp
    }
}

/// Convenience
pub fn XML<R: Read>(mut r: R) -> Result<Document, &'static str> {
    let mut xml_str = String::new();
    r.read_to_string(&mut xml_str).expect("Could not read_to_string");
    println!("ergo::XML()");
    xml::parse_string(&xml_str)
}

pub fn XML2<R: XmlInput + ?Sized>(r:&R) -> Result<Document, &'static str> {
    println!("ergo::XML2()");
    match r.is_path() {
        true => xml::parse_file(&r.data()),
        false => xml::parse_string(&r.data())
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use super::*;
    #[test]
    fn ergo_test(){
        assert!(XML("<root></root>".as_bytes()).is_ok());
        assert!(XML(File::open("tests/resources/file01.xml").unwrap()).is_ok());
        assert!(XML2("<root></root>").is_ok());
        assert!(XML2(&String::from("<root></root>")).is_ok());
        assert!(XML2(&File::open("tests/resources/file01.xml").unwrap()).is_ok());
        assert!(XML2(Path::new("tests/resources/file01.xml")).is_ok());
    }
}
dginev commented 6 years ago

I am definitely fond of the ergonomics and can see such high level constructors as part of the crate.

The naming is a bit of a tricky bit, would love to make it as intuitive as possible without risking confusion.