如何使用 xml-rs 捕获一些值(如果可能的话)

How to capture some values using xml-rs (if it's possible)

我正在使用 xml-rs 0.4,我需要捕获几个字段和值:

来自这个示例 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="rsTest+" version="1.00"/>
  <object class="rsTestWindow" id="window1">
    <property name="can_focus">False</property>
  </object>
</interface>

在查看 Github 中的 xml-rs 代码后,我能够捕获 name"visible":

for att in attributes {
    // test
    let temp_name_local_name = att.name.local_name.clone();
    let temp_value= att.value.clone();

    println!("{}+{}+{}", temp_name_local_name, temp_value);
}

标准输出:

name+visible

我不知道如何捕获 True

这是我的完整代码:

extern crate xml;

use std::fs::File;
use std::io::BufReader;

use xml::reader::{EventReader, XmlEvent};
use xml::name::{Name, OwnedName};

fn indent(size: usize) -> String {
    const INDENT: &'static str = "    ";
    (0..size)
        .map(|_| INDENT)
        .fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}

fn main() {
    let file = File::open("./src/sample.xml").unwrap();
    let file = BufReader::new(file);

    let parser = EventReader::new(file);
    let mut depth = 0;

    for e in parser {
        match e {
            Ok(XmlEvent::StartElement {
                   name,
                   attributes,
                   namespace,
               }) => {

                /* //test
                    let n: xml::namespace::Namespace = namespace;

                    if n.is_empty() {
                        println!("empty");
                    }else{
                        println!("no empty");
                    }
                    */

                let t: String = name.local_name;
                println!("{}", t);

                if name.prefix.is_some() == true {
                    println!("{}", name.prefix.clone().unwrap().clone());
                }
                if name.namespace.is_some() == true {
                    println!("{}", name.namespace.unwrap().clone());
                }

                if attributes.is_empty() == true {
                    //"test".to_string()
                } else {

                    for att in attributes {

                        //let tet: xml::name::OwnedName = att.name;
                        let temp_name_local_name = att.name.local_name.clone();
                        let temp_value = att.value.clone();

                        println!("{}+{}", temp_name_local_name, temp_value);

                        /* //test
                            if att.name.namespace.is_some() == true {
                                 println!("{}", att.name.namespace.unwrap().clone());
                            }
                            if att.name.prefix.is_some() == true {
                                 println!("{}", att.name.prefix.unwrap().clone());
                            }
                            */
                    }
                }
                depth += 1;
            }
            Ok(XmlEvent::ProcessingInstruction { name, data }) => {
                /* //test
                    if data.is_some() == true {
                        println!("{}", data.unwrap().clone());
                    }
                    println!("{}", name );
                    */
            }
            Ok(XmlEvent::EndElement { name }) => {
                //println!("{}-{}", indent(depth), name);
            }
            Err(e) => {
                //println!("Error: {}", e);
                break;
            }
            _ => {}
        }
    }
}

以及我在 Cargo.toml 中的依赖项:

[dependencies]
xml-rs = "0.4"

由于 xml-rs 是拉式解析器,XML 元素的每个结构部分都被多个事件捕获,在本例中是类型 XmlEvent。即,XmlEvent::StartElement 在解析开始(或无实体)XML 标记后触发,并提供元素的名称、名称空间和属性列表。 另一方面,XmlEvent::Characters 捕获 XML 标签之间的文本。这是您的模式匹配中缺少的事件。

在您的情况下,这意味着您必须跟踪最后输入的元素,以便将该文本分配给条目。一种可能的解决方案是保留一个可变记录,并在元素的末尾使用它,它将是完整的。

let mut record = MyStruct { /* ... */ };

for e in parser {
    match e {
        Ok(XmlEvent::StartElement { name, attributes, namespace }) => {
           record.name = name; 
           // ...
        }
        Ok(XmlEvent::Characters(text)) => {
            record.value = text; // or something else
        }
        Ok(XmlEvent::EndElement { .. }) => {
           // record is finished, use it or save it here
           // ...
        }
        // ...
    }
}

理想情况下,您可以构建自己的迭代器类型,将 XMLEvent 抽象出来,并提供对完整记录的迭代。这是我的一个项目中的 example