sxd-document / sxd-xpath не может проанализировать XML - PullRequest
0 голосов
/ 16 января 2019

Я не могу понять, почему это не работает. У меня есть внешний 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

Ответы [ 3 ]

0 голосов
/ 16 января 2019

Ваш XML-файл использует нестандартное пространство имен rdf, но не определяет его. Вам необходимо определить пространство имен в XML:

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

Некоторые анализаторы XML позволяют вам объявлять пространства имен в вашем коде вне XML-документа, но я не нашел ничего подобного после быстрого просмотра в sxd_document документах .

0 голосов
/ 16 января 2019

Ваш код синтаксического анализа 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">

После этих изменений ваша проблема должна быть решена

0 голосов
/ 16 января 2019

Учитывая сообщение об ошибке, я ожидаю, что вам необходимо объявить пространство имен rdf, прежде чем использовать его в имени атрибута rdf:resource.

(Ваша проблема не имеет ничего общего с XPath - она ​​завершается неудачно при попытке проанализировать XML перед запуском любого кода XPath.)

...