Skip to content

Commit

Permalink
feat: support custom parser and derive options in binary
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomblin committed Dec 6, 2023
1 parent 4652e75 commit 08ae70b
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xml_schema_generator"
version = "0.6.0"
version = "0.6.1"
description = "Create Rust struct for given XML file, that allows to deserliaze the given XML using serde or vice versa"
authors = ["Sebastian Detert <rust-crates@elygor.de>"]
edition = "2021"
Expand Down
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ You can add this dependency with:

```toml
[dependencies]
xml_schema_generator = "0.6.0"
xml_schema_generator = "0.6.1"
```

## Example
Expand Down Expand Up @@ -46,15 +46,17 @@ or download the latest binary at [GitHub](https://github.com/Thomblin/xml_schema

How to run the binary
```bash
# parse input.xml and print struct to stdout
$ cargo run --features="env_logger" -- input.xml
# if installed
$ xml_schema_generator input.xml

# parse input.xml and store struct to output.rs
$ cargo run --features="env_logger" -- input.xml output.rs
# if installed
$ xml_schema_generator input.xml output.rs
Usage: xml_schema_generator [OPTIONS] <INPUT_PATH> [OUTPUT_PATH]

Arguments:
<INPUT_PATH> xml file that shall be parsed
[OUTPUT_PATH] rust file to store the result, or none to print to stdout

Options:
-p, --parser <PARSER> define the parser that is used to parse the resulting struct [default: quick-xml-de] [possible values: quick-xml-de, serde-xml-rs]
-d, --derive <DERIVE> define the #derive attribute to be added to each resulting struct [default: "Serialize, Deserialize"]
-h, --help Print help
-V, --version Print version
```

# Contribution
Expand All @@ -78,11 +80,11 @@ Just create a well tested Pull Request in github
☑ added serde_xml_rs support

☑ added Option to change the derive attribute

☑ add Options (serde_xml_rs and derive attribute) to binary

# Ideas (if needed or requested via github)

☐ add Options (serde_xml_rs and derive attribute) to binary

☐ properly parse namespaces and reflect them in the Rust Struct

☐ detect numeric and boolean fields
Expand Down
37 changes: 37 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! defines the command line arguments that can be passed to xml_schema_generator
use clap::Parser;
use xml_schema_generator::Options;

/// collection of command line arguments
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Args {
/// define the parser that is used to parse the resulting struct
#[clap(short, long, default_value_t, value_enum)]
pub parser: ParserArg,
/// define the #derive attribute to be added to each resulting struct
#[clap(short, long, default_value = "Serialize, Deserialize")]
pub derive: String,
/// xml file that shall be parsed
pub input_path: String,
/// rust file to store the result, or none to print to stdout
pub output_path: Option<String>,
}

/// supported parser variants
#[derive(clap::ValueEnum, Clone, Default, Debug)]
pub enum ParserArg {
#[default]
QuickXmlDe,
SerdeXmlRs,
}

/// simplify conversion of argument into parsing options
impl Into<Options> for ParserArg {
fn into(self) -> Options {
match self {
Self::QuickXmlDe => Options::quick_xml_de(),
Self::SerdeXmlRs => Options::serde_xml_rs(),
}
}
}
20 changes: 11 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@
//! or download the latest binary at [GitHub](https://github.com/Thomblin/xml_schema_generator/releases)
//!
//! How to run the binary
//! ```bash
//! # parse input.xml and print struct to stdout
//! $ cargo run --features="env_logger" -- input.xml
//! # if installed
//! $ xml_schema_generator input.xml
//! ```bash//!
//! Usage: xml_schema_generator [OPTIONS] <INPUT_PATH> [OUTPUT_PATH]
//!
//! Arguments:
//! <INPUT_PATH> xml file that shall be parsed
//! [OUTPUT_PATH] rust file to store the result, or none to print to stdout
//!
//! # parse input.xml and store struct to output.rs
//! $ cargo run --features="env_logger" -- input.xml output.rs
//! # if installed
//! $ xml_schema_generator input.xml output.rs
//! Options:
//! -p, --parser <PARSER> define the parser that is used to parse the resulting struct [default: quick-xml-de] [possible values: quick-xml-de, serde-xml-rs]
//! -d, --derive <DERIVE> define the #derive attribute to be added to each resulting struct [default: "Serialize, Deserialize"]
//! -h, --help Print help
//! -V, --version Print version
//! ```

#[macro_use]
Expand Down
33 changes: 14 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
//! run the xml_schema_generator lib as CLI
//! read an xml file
//! print the resulting struct either to stdout or save in a file
mod args;

use args::Args;
use xml_schema_generator::into_struct;
use xml_schema_generator::Options;

use clap::Parser;
use log::{error, info};
use quick_xml::reader::Reader;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::process;
use xml_schema_generator::Options;

use quick_xml::reader::Reader;

use xml_schema_generator::into_struct;

// store input and output options
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Config {
/// xml file that shall be parsed
input_path: String,
/// rust file to store the result, or none to print to stdout
output_path: Option<String>,
}

fn main() {
env_logger::init();

let config = Config::parse();
let config = Args::parse();

run(config).unwrap_or_else(|err| {
error!("{err}");
Expand All @@ -35,15 +27,18 @@ fn main() {
}

// read file, generate struct and print/store the result
fn run(config: Config) -> Result<(), Box<dyn std::error::Error>> {
fn run(config: Args) -> Result<(), Box<dyn std::error::Error>> {
info!("read {}", config.input_path);
let xml = fs::read_to_string(config.input_path)?;
let mut reader = Reader::from_str(&xml);

let root = into_struct(&mut reader)?;

let struct_as_string = "use serde::{Deserialize, Serialize};\n\n".to_owned()
+ &root.to_serde_struct(&Options::quick_xml_de());
let mut options: Options = config.parser.into();
options = options.derive(&config.derive);

let struct_as_string =
"use serde::{Deserialize, Serialize};\n\n".to_owned() + &root.to_serde_struct(&options);

match config.output_path {
Some(output_path) => {
Expand Down
10 changes: 10 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
//! configures how the resulting struct needs to be formatted to support a specific parser
//! currently supports quick_xml::de and serde_xml_rs

/// configuration of target parser
pub struct Options {
/// representation of text content
pub text_identifier: String,
/// representation of element attributes
pub attribute_prefix: String,
/// derive attribute that shall be added to each resulting struct
pub derive: String,
}

impl Options {
/// format struct compatible with quick_xml::de
pub fn quick_xml_de() -> Self {
Self {
text_identifier: "$text".to_string(),
Expand All @@ -13,6 +21,7 @@ impl Options {
}
}

/// format struct compatible with serde_xml_rs
pub fn serde_xml_rs() -> Self {
Self {
text_identifier: "$text".to_string(),
Expand All @@ -21,6 +30,7 @@ impl Options {
}
}

/// define a custome #derive attribute
pub fn derive(mut self, derive: &str) -> Self {
self.derive = derive.to_string();
self
Expand Down

0 comments on commit 08ae70b

Please sign in to comment.