Added XML support for load_data (#1769)
Co-authored-by: doomy <2640792-_doomy@users.noreply.gitlab.com>
This commit is contained in:
parent
a67370b8d8
commit
88e0624f11
|
@ -1412,6 +1412,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
|
"quickxml_to_serde",
|
||||||
"rayon",
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
"relative-path",
|
"relative-path",
|
||||||
|
@ -1640,6 +1641,15 @@ dependencies = [
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minidom"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe549115a674f5ec64c754d85e37d6f42664bd0ef4ffb62b619489ad99c6cb1a"
|
||||||
|
dependencies = [
|
||||||
|
"quick-xml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minify-html"
|
name = "minify-html"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -2387,6 +2397,27 @@ version = "1.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-xml"
|
||||||
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quickxml_to_serde"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26f35112b35480fd72f63444289083eeedbd61d13907c82c4309f0ccda35e244"
|
||||||
|
dependencies = [
|
||||||
|
"minidom",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
|
|
@ -10,6 +10,7 @@ csv = "1"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
|
quickxml_to_serde = "0.5"
|
||||||
url = "2"
|
url = "2"
|
||||||
syntect = "4"
|
syntect = "4"
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub use num_format;
|
||||||
pub use once_cell;
|
pub use once_cell;
|
||||||
pub use percent_encoding;
|
pub use percent_encoding;
|
||||||
pub use pulldown_cmark;
|
pub use pulldown_cmark;
|
||||||
|
pub use quickxml_to_serde;
|
||||||
pub use rayon;
|
pub use rayon;
|
||||||
pub use regex;
|
pub use regex;
|
||||||
pub use relative_path;
|
pub use relative_path;
|
||||||
|
|
|
@ -46,6 +46,7 @@ enum OutputFormat {
|
||||||
Csv,
|
Csv,
|
||||||
Bibtex,
|
Bibtex,
|
||||||
Plain,
|
Plain,
|
||||||
|
Xml,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for OutputFormat {
|
impl FromStr for OutputFormat {
|
||||||
|
@ -57,6 +58,7 @@ impl FromStr for OutputFormat {
|
||||||
"csv" => Ok(OutputFormat::Csv),
|
"csv" => Ok(OutputFormat::Csv),
|
||||||
"json" => Ok(OutputFormat::Json),
|
"json" => Ok(OutputFormat::Json),
|
||||||
"bibtex" => Ok(OutputFormat::Bibtex),
|
"bibtex" => Ok(OutputFormat::Bibtex),
|
||||||
|
"xml" => Ok(OutputFormat::Xml),
|
||||||
"plain" => Ok(OutputFormat::Plain),
|
"plain" => Ok(OutputFormat::Plain),
|
||||||
format => Err(format!("Unknown output format {}", format).into()),
|
format => Err(format!("Unknown output format {}", format).into()),
|
||||||
}
|
}
|
||||||
|
@ -70,6 +72,7 @@ impl OutputFormat {
|
||||||
OutputFormat::Csv => "text/csv",
|
OutputFormat::Csv => "text/csv",
|
||||||
OutputFormat::Toml => "application/toml",
|
OutputFormat::Toml => "application/toml",
|
||||||
OutputFormat::Bibtex => "application/x-bibtex",
|
OutputFormat::Bibtex => "application/x-bibtex",
|
||||||
|
OutputFormat::Xml => "text/xml",
|
||||||
OutputFormat::Plain => "text/plain",
|
OutputFormat::Plain => "text/plain",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -368,6 +371,7 @@ impl TeraFn for LoadData {
|
||||||
OutputFormat::Csv => load_csv(data),
|
OutputFormat::Csv => load_csv(data),
|
||||||
OutputFormat::Json => load_json(data),
|
OutputFormat::Json => load_json(data),
|
||||||
OutputFormat::Bibtex => load_bibtex(data),
|
OutputFormat::Bibtex => load_bibtex(data),
|
||||||
|
OutputFormat::Xml => load_xml(data),
|
||||||
OutputFormat::Plain => to_value(data).map_err(|e| e.into()),
|
OutputFormat::Plain => to_value(data).map_err(|e| e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -502,6 +506,42 @@ fn load_csv(csv_data: String) -> Result<Value> {
|
||||||
to_value(csv_value).map_err(|err| err.into())
|
to_value(csv_value).map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an XML string and convert it to a Tera Value
|
||||||
|
///
|
||||||
|
/// An example XML file `example.xml` could be:
|
||||||
|
/// ```xml
|
||||||
|
/// <root>
|
||||||
|
/// <headers>Number</headers>
|
||||||
|
/// <headers>Title</headers>
|
||||||
|
/// <records>
|
||||||
|
/// <item>1</item>
|
||||||
|
/// <item>Gutenberg</item>
|
||||||
|
/// </records>
|
||||||
|
/// <records>
|
||||||
|
/// <item>2</item>
|
||||||
|
/// <item>Printing</item>
|
||||||
|
/// </records>
|
||||||
|
/// </root>
|
||||||
|
/// ```
|
||||||
|
/// The json value output would be:
|
||||||
|
/// ```json
|
||||||
|
/// {
|
||||||
|
/// "root": {
|
||||||
|
/// "headers": ["Number", "Title"],
|
||||||
|
/// "records": [
|
||||||
|
/// ["1", "Gutenberg"],
|
||||||
|
/// ["2", "Printing"]
|
||||||
|
/// ]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn load_xml(xml_data: String) -> Result<Value> {
|
||||||
|
let xml_content: Value =
|
||||||
|
libs::quickxml_to_serde::xml_string_to_json(xml_data, &Default::default())
|
||||||
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
|
Ok(xml_content)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{DataSource, LoadData, OutputFormat};
|
use super::{DataSource, LoadData, OutputFormat};
|
||||||
|
@ -1007,6 +1047,27 @@ mod tests {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_load_xml() {
|
||||||
|
let static_fn = LoadData::new(PathBuf::from("../utils/test-files"), None, PathBuf::new());
|
||||||
|
let mut args = HashMap::new();
|
||||||
|
args.insert("path".to_string(), to_value("test.xml").unwrap());
|
||||||
|
let result = static_fn.call(&args.clone()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
json!({
|
||||||
|
"root": {
|
||||||
|
"key": "value",
|
||||||
|
"array": [1, 2, 3],
|
||||||
|
"subpackage": {
|
||||||
|
"subkey": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn is_load_remote_data_using_post_method_with_different_body_not_cached() {
|
fn is_load_remote_data_using_post_method_with_different_body_not_cached() {
|
||||||
let _mjson = mock("POST", "/kr1zdgbm4y3")
|
let _mjson = mock("POST", "/kr1zdgbm4y3")
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<root>
|
||||||
|
<key>value</key>
|
||||||
|
<array>1</array>
|
||||||
|
<array>2</array>
|
||||||
|
<array>3</array>
|
||||||
|
<subpackage>
|
||||||
|
<subkey>5</subkey>
|
||||||
|
</subpackage>
|
||||||
|
</root>
|
|
@ -258,7 +258,7 @@ The method returns a map containing `width`, `height` and `format` (the lowercas
|
||||||
```
|
```
|
||||||
|
|
||||||
### `load_data`
|
### `load_data`
|
||||||
Loads data from a file or URL. Supported file types include *toml*, *json*, *csv* and *bibtex* and only supports UTF-8 encoding.
|
Loads data from a file or URL. Supported file types include *toml*, *json*, *csv*, *bibtex* and *xml* and only supports UTF-8 encoding.
|
||||||
Any other file type will be loaded as plain text.
|
Any other file type will be loaded as plain text.
|
||||||
|
|
||||||
The `path` argument specifies the path to a local data file, according to the [File Searching Logic](@/documentation/templates/overview.md#file-searching-logic).
|
The `path` argument specifies the path to a local data file, according to the [File Searching Logic](@/documentation/templates/overview.md#file-searching-logic).
|
||||||
|
@ -283,17 +283,16 @@ The snippet below outputs the HTML from a Wikipedia page, or "No data found" if
|
||||||
```
|
```
|
||||||
|
|
||||||
The optional `format` argument allows you to specify and override which data type is contained
|
The optional `format` argument allows you to specify and override which data type is contained
|
||||||
within the specified file or URL. Valid entries are `toml`, `json`, `csv`, `bibtex`
|
within the specified file or URL. Valid entries are `toml`, `json`, `csv`, `bibtex`, `xml` or `plain`. If the `format` argument isn't specified, then the path extension is used.
|
||||||
or `plain`. If the `format` argument isn't specified, then the path extension is used.
|
|
||||||
|
|
||||||
|
|
||||||
```jinja2
|
```jinja2
|
||||||
{% set data = load_data(path="content/blog/story/data.txt", format="json") %}
|
{% set data = load_data(path="content/blog/story/data.txt", format="json") %}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use the `plain` format for when your file has a toml/json/csv extension but you want to load it as plain text.
|
Use the `plain` format for when your file has a supported extension but you want to load it as plain text.
|
||||||
|
|
||||||
For *toml* and *json*, the data is loaded into a structure matching the original data file;
|
For *toml*, *json* and *xml*, the data is loaded into a structure matching the original data file;
|
||||||
however, for *csv* there is no native notion of such a structure. Instead, the data is separated
|
however, for *csv* there is no native notion of such a structure. Instead, the data is separated
|
||||||
into a data structure containing *headers* and *records*. See the example below to see
|
into a data structure containing *headers* and *records*. See the example below to see
|
||||||
how this works.
|
how this works.
|
||||||
|
|
Loading…
Reference in New Issue