如何使用 xml-rs 捕获一些值(如果可能的话)
How to capture some values using xml-rs (if it's possible)
我正在使用 xml-rs 0.4,我需要捕获几个字段和值:
- 姓名
- "visible"
- 正确
来自这个示例 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。
我正在使用 xml-rs 0.4,我需要捕获几个字段和值:
- 姓名
- "visible"
- 正确
来自这个示例 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。