mirror of
https://github.com/nushell/nushell.git
synced 2025-08-24 23:45:40 +02:00
Make xml:
prefix always available in query xml
(#16472)
## Release notes summary - What our users need to know `query xml` now has `xml:` namespace prefix available by default, without the need to specify it via `--namespaces`. ## Details and motivation `xml:` prefix is rarely (if ever) explicitly declared in XML sources, so its associated namespace is a bit obscure. `sxd_xpath` seems to assume it's `http://www.w3.org/XML/1998/namespace`, so we register it by default. ## Tasks after submitting <!-- Remove any tasks which aren't relevant for your PR, or add your own --> - [ ] Update the [documentation](https://github.com/nushell/nushell.github.io)
This commit is contained in:
@@ -66,14 +66,14 @@ Output of the nodeset results depends on the flags used:
|
|||||||
Example {
|
Example {
|
||||||
description: "Query namespaces on the root element of an SVG file",
|
description: "Query namespaces on the root element of an SVG file",
|
||||||
example: r#"http get --raw https://www.w3.org/TR/SVG/images/conform/smiley.svg
|
example: r#"http get --raw https://www.w3.org/TR/SVG/images/conform/smiley.svg
|
||||||
| query xml '/svg:svg/namespace::*' --output-string-value --output-names --namespaces {svg: "http://www.w3.org/2000/svg"}"#,
|
| query xml '/svg:svg/namespace::*' --output-string-value --output-names --output-type --namespaces {svg: "http://www.w3.org/2000/svg"}"#,
|
||||||
result: None,
|
result: None,
|
||||||
},
|
},
|
||||||
// scalar output
|
// scalar output
|
||||||
Example {
|
Example {
|
||||||
description: "Query number of stylesheets SVG file has",
|
description: "Query the language of Nushell blog (`xml:` prefix is always available)",
|
||||||
example: r#"http get --raw https://www.w3.org/TR/SVG/images/conform/smiley.svg
|
example: r#"http get --raw https://www.nushell.sh/atom.xml
|
||||||
| query xml 'count(//svg:style)' --namespaces {svg: "http://www.w3.org/2000/svg"}"#,
|
| query xml 'string(/*/@xml:lang)'"#,
|
||||||
result: None,
|
result: None,
|
||||||
},
|
},
|
||||||
// query attributes
|
// query attributes
|
||||||
@@ -85,9 +85,9 @@ Output of the nodeset results depends on the flags used:
|
|||||||
},
|
},
|
||||||
// default output
|
// default output
|
||||||
Example {
|
Example {
|
||||||
description: "Get recent Debian news",
|
description: "Get recent Nushell news",
|
||||||
example: r#"http get --raw https://www.debian.org/News/news
|
example: r#"http get --raw https://www.nushell.sh/atom.xml
|
||||||
| query xml '//item/title|//item/link'
|
| query xml '//atom:entry/atom:title|//atom:entry/atom:link/@href' --namespaces {atom: "http://www.w3.org/2005/Atom"}
|
||||||
| window 2 --stride 2
|
| window 2 --stride 2
|
||||||
| each { {title: $in.0.string_value, link: $in.1.string_value} }"#,
|
| each { {title: $in.0.string_value, link: $in.1.string_value} }"#,
|
||||||
result: None,
|
result: None,
|
||||||
@@ -141,7 +141,22 @@ pub fn execute_xpath_query(
|
|||||||
let document = package.as_document();
|
let document = package.as_document();
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
|
|
||||||
for (prefix, uri) in namespaces.unwrap_or_default().into_iter() {
|
let mut namespaces = namespaces.unwrap_or_default();
|
||||||
|
|
||||||
|
if namespaces.get("xml").is_none() {
|
||||||
|
// XML namespace is always present, so we add it explicitly
|
||||||
|
// it's used in attributes like `xml:lang`, `xml:base`, etc.
|
||||||
|
namespaces.insert(
|
||||||
|
"xml",
|
||||||
|
Value::string("http://www.w3.org/XML/1998/namespace", call.head),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: `xmlns:whatever=` or `xmlns=` may look like an attribute, but XPath doesn't treat it as such.
|
||||||
|
// Those are namespaces, and they are available through a separate axis (`namespace::`)
|
||||||
|
// Thus we don't need to register a namespace for `xmlns` prefix
|
||||||
|
|
||||||
|
for (prefix, uri) in namespaces.into_iter() {
|
||||||
context.set_namespace(prefix.as_str(), uri.into_string()?.as_str());
|
context.set_namespace(prefix.as_str(), uri.into_string()?.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,4 +562,26 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(actual, expected);
|
assert_eq!(actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn xml_namespace_is_always_present() {
|
||||||
|
let call = EvaluatedCall {
|
||||||
|
head: Span::test_data(),
|
||||||
|
positional: vec![],
|
||||||
|
named: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = Value::test_string(
|
||||||
|
r#"<?xml version="1.0" encoding="UTF-8"?><elt xml:lang="en">hello</elt>"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let spanned_str: Spanned<String> = Spanned {
|
||||||
|
item: "string(/elt/@xml:lang)".to_string(),
|
||||||
|
span: Span::test_data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let actual = query(&call, &text, Some(spanned_str), None).expect("test should not fail");
|
||||||
|
|
||||||
|
assert_eq!(actual, Value::test_string("en"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user