-
Notifications
You must be signed in to change notification settings - Fork 34
Open
Description
I was porting my Ruby code which uses the Nokogiri library to sxd-xpath and was very confused why none of my xpaths were working anymore, and after some searching around I found #138
So copy-pasting the examples from that issue, this doesn't work:
let package = sxd_document::parser::parse("<root xmlns=\"https://some.place.com/metadata\">hello</root>").expect("failed to parse XML");
let document = package.as_document();
let value = sxd_xpath::evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
assert_eq!("hello", value.string());but this does:
let package = sxd_document::parser::parse("<root xmlns=\"https://some.place.com/metadata\">hello</root>").expect("failed to parse XML");
let document = package.as_document();
let mut context = sxd_xpath::Context::new();
context.set_namespace("foobar", "https://some.place.com/metadata");
let xpath = sxd_xpath::Factory::new().build("/foobar:root").expect("Unable to build xpath").expect("Unable to build xpath");
let value = xpath.evaluate(&context, document.root()).expect("XPath evaluation failed");
assert_eq!("hello", value.string());It would be nice to have a way to at least disable this behavior, although in my opinion it shouldn't be the default. It's unergonomic, the vast majority of XML files don't need it, and at least some other XML libraries (e.g. Nokogiri) don't work this way.
A quick (and somewhat silly) workaround:
fn remove_namespaces(xml: &str) -> String {
let mut reader = quick_xml::Reader::from_str(xml);
let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
loop {
match reader.read_event().unwrap() {
quick_xml::events::Event::Eof => break,
quick_xml::events::Event::Start(e) if e.try_get_attribute("xmlns").unwrap().is_some() => {
let mut new_e = e.to_owned();
new_e.clear_attributes();
for attr in e.attributes() {
let attr = attr.unwrap();
if attr.key.0 == b"xmlns" {
continue;
}
new_e.push_attribute(attr);
}
writer.write_event(quick_xml::events::Event::Start(new_e)).unwrap()
},
e => writer.write_event(e).unwrap()
}
}
String::from_utf8(writer.into_inner().into_inner()).unwrap()
}...and with this it works:
let xml = "<root xmlns=\"https://some.place.com/metadata\">hello</root>";
let xml = remove_namespaces(xml);
let package = sxd_document::parser::parse(&xml).expect("failed to parse XML");
let document = package.as_document();
let value = sxd_xpath::evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
assert_eq!("hello", value.string());mcpar-land
Metadata
Metadata
Assignees
Labels
No labels