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">

经过这些修改后,你的问题应该就解决了