sxd-document / sxd-xpath 无法解析 XML
sxd-document / sxd-xpath failing to parse XML
我似乎无法弄清楚为什么这不起作用。我有一个外部 XML 文件,我正试图通过 XPath 遍历它。
我的代码是:
extern crate sxd_document;
extern crate sxd_xpath;
use std::fs;
use sxd_document::parser;
use sxd_xpath::{evaluate_xpath, Value};
fn main() {
let contents = fs::read_to_string("./spec/organisation.xml")
.expect("Something went wrong reading the file");
// let package = parser::parse("<root>hello</root>").expect("failed to parse XML");
let package = parser::parse(&contents).expect("failed to parse XML");
let document = package.as_document();
let value = evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
assert_eq!("hello", value.string());
}
XML是:
<organisation xml:id="a17649">
<code rdf:resource="http://pbs.gov.au/code/manufacturer">CU</code>
<title>Care Pharmaceuticals Pty Limited</title>
<address>
<dbk:street>Suite 303, Level 3, 59-75 Grafton Street</dbk:street>
<dbk:city>Bondi Junction</dbk:city>
<dbk:state>NSW</dbk:state>
<dbk:postcode>2022</dbk:postcode>
<effective>
<date>2018-12-01</date>
</effective>
</address>
<contact>
<dbk:phone>1800 788 870</dbk:phone>
<effective>
<date>2018-12-01</date>
</effective>
</contact>
<effective>
<date>2012-08-27</date>
</effective>
</organisation>
堆栈跟踪看起来像:
Running `target/debug/pbs`
thread 'main' panicked at 'failed to parse XML: Error { location: 50, errors: {UnknownNamespacePrefix} }', libcore/result.rs:1009:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print
at libstd/sys_common/backtrace.rs:71
at libstd/sys_common/backtrace.rs:59
2: std::panicking::default_hook::{{closure}}
at libstd/panicking.rs:211
3: std::panicking::default_hook
at libstd/panicking.rs:227
4: std::panicking::rust_panic_with_hook
at libstd/panicking.rs:476
5: std::panicking::continue_panic_fmt
at libstd/panicking.rs:390
6: rust_begin_unwind
at libstd/panicking.rs:325
7: core::panicking::panic_fmt
at libcore/panicking.rs:77
8: core::result::unwrap_failed
at libcore/macros.rs:26
9: <core::result::Result<T, E>>::expect
at libcore/result.rs:835
10: pbs::main
at src/main.rs:14
11: std::rt::lang_start::{{closure}}
at libstd/rt.rs:74
12: std::panicking::try::do_call
at libstd/rt.rs:59
at libstd/panicking.rs:310
13: __rust_maybe_catch_panic
at libpanic_unwind/lib.rs:102
14: std::rt::lang_start_internal
at libstd/panicking.rs:289
at libstd/panic.rs:392
at libstd/rt.rs:58
15: std::rt::lang_start
at libstd/rt.rs:74
16: main
17: __libc_start_main
18: _start
根据错误消息,我认为您需要先声明 rdf
命名空间,然后再在 rdf:resource
属性名称上使用它。
(您的问题与 XPath 没有任何关系——在任何 XPath 代码被 运行 之前尝试解析 XML 时失败。)
您的 XML 文件使用了非标准的 rdf
命名空间,但未对其进行定义。您需要在 XML:
中定义命名空间
<organisation xml:id="a17649"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
一些 XML 解析器允许您在 XML 文档之外的代码中声明名称空间,但在快速查看 sxd_document
docs.
当 XML 内容正确时,您的 XML 解析代码应该可以正常工作。
虽然它在快乐路径中没有问题,但由于您在代码中使用 expect
而不是错误处理,程序在错误场景中会出现混乱。
您可以将代码更改为以下代码以更好地打印错误:
let package = parser::parse(&contents);
match package {
Ok(package) => {
let document = package.as_document();
let value = evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
println!("value: {:?}", value);
}
Err(err) => {
println!("{:?}", err);
}
}
修复后,您会注意到代码打印出 UnknownNamespacePrefix
错误。
当 XML 内容具有未在 XML 文件本身中声明的命名空间时,会发生此错误。
在您的 XML 文件中,您需要指定您的名称空间,但您没有为以下内容指定名称空间:
<organisation xml:id="a17649">
您需要添加命名空间:
<organisation xml:id="a17649" xmlns:rdf="http://www.w3.org/1999/xhtml">
即使您像这样声明了 rdf
命名空间,您也在使用 dbk
命名空间,这可能取决于您的项目本身。您还需要指定此命名空间:
<organisation xml:id="a17649" xmlns:rdf="http://www.w3.org/1999/xhtml" xmlns:dbk="/path/to/dbk">
经过这些修改后,你的问题应该就解决了
我似乎无法弄清楚为什么这不起作用。我有一个外部 XML 文件,我正试图通过 XPath 遍历它。
我的代码是:
extern crate sxd_document;
extern crate sxd_xpath;
use std::fs;
use sxd_document::parser;
use sxd_xpath::{evaluate_xpath, Value};
fn main() {
let contents = fs::read_to_string("./spec/organisation.xml")
.expect("Something went wrong reading the file");
// let package = parser::parse("<root>hello</root>").expect("failed to parse XML");
let package = parser::parse(&contents).expect("failed to parse XML");
let document = package.as_document();
let value = evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
assert_eq!("hello", value.string());
}
XML是:
<organisation xml:id="a17649">
<code rdf:resource="http://pbs.gov.au/code/manufacturer">CU</code>
<title>Care Pharmaceuticals Pty Limited</title>
<address>
<dbk:street>Suite 303, Level 3, 59-75 Grafton Street</dbk:street>
<dbk:city>Bondi Junction</dbk:city>
<dbk:state>NSW</dbk:state>
<dbk:postcode>2022</dbk:postcode>
<effective>
<date>2018-12-01</date>
</effective>
</address>
<contact>
<dbk:phone>1800 788 870</dbk:phone>
<effective>
<date>2018-12-01</date>
</effective>
</contact>
<effective>
<date>2012-08-27</date>
</effective>
</organisation>
堆栈跟踪看起来像:
Running `target/debug/pbs`
thread 'main' panicked at 'failed to parse XML: Error { location: 50, errors: {UnknownNamespacePrefix} }', libcore/result.rs:1009:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print
at libstd/sys_common/backtrace.rs:71
at libstd/sys_common/backtrace.rs:59
2: std::panicking::default_hook::{{closure}}
at libstd/panicking.rs:211
3: std::panicking::default_hook
at libstd/panicking.rs:227
4: std::panicking::rust_panic_with_hook
at libstd/panicking.rs:476
5: std::panicking::continue_panic_fmt
at libstd/panicking.rs:390
6: rust_begin_unwind
at libstd/panicking.rs:325
7: core::panicking::panic_fmt
at libcore/panicking.rs:77
8: core::result::unwrap_failed
at libcore/macros.rs:26
9: <core::result::Result<T, E>>::expect
at libcore/result.rs:835
10: pbs::main
at src/main.rs:14
11: std::rt::lang_start::{{closure}}
at libstd/rt.rs:74
12: std::panicking::try::do_call
at libstd/rt.rs:59
at libstd/panicking.rs:310
13: __rust_maybe_catch_panic
at libpanic_unwind/lib.rs:102
14: std::rt::lang_start_internal
at libstd/panicking.rs:289
at libstd/panic.rs:392
at libstd/rt.rs:58
15: std::rt::lang_start
at libstd/rt.rs:74
16: main
17: __libc_start_main
18: _start
根据错误消息,我认为您需要先声明 rdf
命名空间,然后再在 rdf:resource
属性名称上使用它。
(您的问题与 XPath 没有任何关系——在任何 XPath 代码被 运行 之前尝试解析 XML 时失败。)
您的 XML 文件使用了非标准的 rdf
命名空间,但未对其进行定义。您需要在 XML:
<organisation xml:id="a17649"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
一些 XML 解析器允许您在 XML 文档之外的代码中声明名称空间,但在快速查看 sxd_document
docs.
当 XML 内容正确时,您的 XML 解析代码应该可以正常工作。
虽然它在快乐路径中没有问题,但由于您在代码中使用 expect
而不是错误处理,程序在错误场景中会出现混乱。
您可以将代码更改为以下代码以更好地打印错误:
let package = parser::parse(&contents);
match package {
Ok(package) => {
let document = package.as_document();
let value = evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
println!("value: {:?}", value);
}
Err(err) => {
println!("{:?}", err);
}
}
修复后,您会注意到代码打印出 UnknownNamespacePrefix
错误。
当 XML 内容具有未在 XML 文件本身中声明的命名空间时,会发生此错误。
在您的 XML 文件中,您需要指定您的名称空间,但您没有为以下内容指定名称空间:
<organisation xml:id="a17649">
您需要添加命名空间:
<organisation xml:id="a17649" xmlns:rdf="http://www.w3.org/1999/xhtml">
即使您像这样声明了 rdf
命名空间,您也在使用 dbk
命名空间,这可能取决于您的项目本身。您还需要指定此命名空间:
<organisation xml:id="a17649" xmlns:rdf="http://www.w3.org/1999/xhtml" xmlns:dbk="/path/to/dbk">
经过这些修改后,你的问题应该就解决了