sxd-document / sxd-xpath无法解析XML

时间:2019-01-16 09:26:19

标签: xml xpath rust xml-namespaces

我似乎无法弄清楚为什么它不起作用。我有一个要通过XPath遍历的外部XML文件。

我的代码是:

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

3 个答案:

答案 0 :(得分:3)

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

这些更改之后,您的问题应该得到解决

答案 1 :(得分:1)

鉴于错误消息,我希望您需要先在rdf属性名称上使用rdf:resource命名空间,然后进行声明。

(您的问题与XPath没有任何关系-在运行任何XPath代码之前尝试解析XML时失败。)

答案 2 :(得分:1)

您的XML文件使用非标准的rdf命名空间,但未定义它。您需要在XML中定义名称空间:

<organisation xml:id="a17649"
              xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

一些XML解析器允许您在XML文档之外的代码中声明名称空间,但是在快速浏览sxd_document docs之后,我没有发现类似的东西。