fix: cli xml LastElementNameNotAvailable error case

This commit is contained in:
Cain 2024-02-02 01:44:44 +00:00
parent 8f381f733c
commit 5365845bb5
3 changed files with 69 additions and 3 deletions

View file

@ -19,7 +19,7 @@ packet_capture = ["gamedig/packet_capture"]
# Output formats
bson = ["dep:serde", "dep:bson", "dep:hex", "dep:base64", "gamedig/serde"]
json = ["dep:serde", "dep:serde_json", "gamedig/serde"]
xml = ["dep:serde", "dep:serde-xml-rs", "gamedig/serde"]
xml = ["dep:serde", "dep:quick-xml", "gamedig/serde"]
# Misc
browser = ["dep:webbrowser"]
@ -47,7 +47,7 @@ hex = { version = "0.4.3", optional = true, default-features = false }
serde_json = { version = "1", optional = true, default-features = false }
# XML
serde-xml-rs = { version = "0.6.0", optional = true, default-features = false }
quick-xml = { version = "0.31.0", optional = true, default-features = false }
# Browser
webbrowser = { version = "0.8.12", optional = true, default-features = false }

View file

@ -11,6 +11,12 @@ pub enum Error {
#[error("Gamedig Error: {0}")]
Gamedig(#[from] gamedig::errors::GDError),
#[error("Serde Error: {0}")]
Serde(#[from] serde_json::Error),
#[error("Xml Error: {0}")]
Xml(#[from] quick_xml::Error),
#[error("Unknown Game: {0}")]
UnknownGame(String),

View file

@ -278,7 +278,67 @@ fn output_result_json_pretty<T: serde::Serialize>(result: T) {
/// * `result` - A serde serializable result.
#[cfg(feature = "xml")]
fn output_result_xml<T: serde::Serialize>(result: T) {
println!("{}", serde_xml_rs::to_string(&result).unwrap());
use quick_xml::events::{BytesEnd, BytesStart, Event, BytesText};
use quick_xml::Writer;
use serde_json::Value;
use std::io::Cursor;
// Serialize the struct to a JSON Value first
let json = serde_json::to_value(result).expect("Failed to serialize struct to JSON");
// Create a buffer and a writer for XML output
let buffer = Cursor::new(Vec::new());
let mut writer = Writer::new(buffer);
// Recursive function to convert JSON to XML
fn json_to_xml<W: std::io::Write>(
writer: &mut Writer<W>,
key: Option<&str>,
value: &Value,
) -> Result<()> {
match value {
Value::Object(obj) => {
if let Some(key) = key {
writer.write_event(Event::Start(BytesStart::new(key)))?;
}
for (k, v) in obj {
json_to_xml(writer, Some(k), v)?;
}
if let Some(key) = key {
writer.write_event(Event::End(BytesEnd::new(key)))?;
}
},
Value::Array(arr) => {
for v in arr {
json_to_xml(writer, key.or(Some("item")), v)?;
}
},
_ => {
if let Some(key) = key {
writer.write_event(Event::Start(BytesStart::new(key)))?;
}
let text_string = match value {
Value::String(s) => s.to_string(),
_ => value.to_string().trim_matches('"').to_string(),
};
let text = text_string.as_str();
writer.write_event(Event::Text(BytesText::new(text)))?;
if let Some(key) = key {
writer.write_event(Event::End(BytesEnd::new(key)))?;
}
}
}
Ok(())
}
writer.write_event(Event::Start(BytesStart::new("data"))).expect("Failed to write start tag");
json_to_xml(&mut writer, None, &json).expect("Failed to convert JSON to XML");
writer.write_event(Event::End(BytesEnd::new("data"))).expect("Failed to write end tag");
let xml_bytes = writer.into_inner().into_inner();
let xml_string = String::from_utf8(xml_bytes).expect("Failed to convert XML bytes to string");
println!("{}", xml_string);
}
/// Output the result as a BSON object encoded as a hex string.