2个版本
0.1.3 | 2024年4月19日 |
---|---|
0.1.2 | 2024年4月19日 |
0.1.1 |
|
32 在 #xml-data 中排名
每月下载 275 次
用于 xavier
9.5MB
1.5K SLoC
包含(Rust库,5.5MB)libsyn-fe13b19e237c3f6d.rlib,(Rust库,1MB)libmemchr-9e426edd08692ba7.rlib,(Rust库,1.5MB)libquick_xml-1ee1e6f88d5ada0d.rlib,(Rust库,1MB)libproc_macro2-e9e571a42aa8fc4b.rlib,(Mach-o可执行文件,520KB)build-script-build,(Mach-o可执行文件,520KB)build_script_build-1c575835abd73bb7 等等。
Xavier是谁?
这是一个新的库,请报告所有错误并帮助我们!
介绍Xavier:一个简化版XML解析库 受Serde启发。为什么是Xavier?嗯...它以X开头,是我首先想到的名字,没有别的。
Xavier是一个轻量级且多功能的XML解析库,旨在简化处理XML数据的便捷性和高效性。
虽然速度是Xavier设计时考虑的因素,但重要的是要强调,原始速度并不是其主要目标。相反,Xavier优先考虑易用性和人体工程学设计,旨在在Rust应用程序中简化XML解析任务,同时不牺牲可靠性或开发者体验。
必须用于相对较小的xml,因为它将所有数据存储在内存中。
注意1:尚不支持UTF-16。努力工作!欢迎PR。
注意2:我们的DOM实现(WIP)旨在尽可能接近原始规范,但由于规范和Rust在处理概念上的差异,实现完美匹配是困难的。
为什么不扩展Serde?
已经有人这样做过了,但我更喜欢从头开始。此外,由于Xavier专注于XML解析,我认为它应该更简单、更符合该目的。
示例
序列化
从简单开始
这是可能的简单示例
#[derive(XmlSerializable)]
struct XMLObject {
pub some_string: String,
pub some_int: i32,
pub some_float: f32
}
// ...
println!(from_obj(&instance));
// ...
应产生
<XMLObject>
<some_string>Some Content A</some_string>
<some_int>0</some_int>
<some_float>0.0</some_float>
</XMLObject>
名称
改进名称
#[derive(XmlSerializable)]
#[xml(name="object", case="Camel", prefix="xml_", suffix="Item", no_suffix, no_prefix)]
struct XMLObject {
#[xml(name="just_string")]
pub some_string: String,
pub some_int: i32,
pub some_float: f32
}
// ...
println!(from_obj(&instance));
// ...
应产生
<object>
<xmlJustStringItem>Some Content A</xmlJustStringItem>
<xmlSomeIntItem>0</xmlSomeIntItem>
<xmlSomeFloatItem>0.0</xmlSomeFloatItem>
</object>
注意1:使用驼峰命名配置将产生所有元素使用相同的约定。
注意2:除了随机数外,convert_case crate支持的所有情况都可以使用。
注意3:可以使用 ignore_case 来忽略元素的大小写。
命名空间
与命名空间一起工作
#[derive(XmlSerializable)]
#[xml(ns="xml", name="object", case="Camel")]
struct XMLObject {
#[xml(xmlns)]
pub namespaces: Namespaces,
#[xml(name="just_string")]
pub some_string: String,
pub some_int: i32,
pub some_float: f32
}
// ...
let xmlns = namespaces!(xml = "http://www.w3.org/XML/1998/namespace", xhtml = "http://www.w3.org/1999/xhtml");
XMLObject{ namespaces: xmlns, ... }
//...
println!(from_obj(&instance));
// ...
应产生
<xml:object
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xml:justString>Some Content A</justString>
<xml:someInt>0</someInt>
<xml:someFloat>0.0</someFloat>
</xml:object>
注意:
#[xml(xmlns)]
必须仅在根元素上使用一次。
属性
与属性一起工作
#[derive(XmlSerializable)]
#[xml(ns="a", name="object", case="Camel")]
struct XMLObject {
#[xml(attribute, name="just_string")]
pub some_string: String,
pub some_int: i32,
pub some_float: f32
}
// ...
println!(from_obj(&instance));
// ...
应产生
<a:xmlObject justString="Some Text">
<a:someInt>0</a:someInt>
<a:someFloat>0</a:someFloat>
</a:xmlObject>
注意:use_suffix="false" 或 use_prefix="true" 可以用来强制使用后缀或前缀。
枚举
与枚举一起工作
#[derive(XmlSerializable)]
enum CustomEnum {
ValueA
}
// Many libs don't implement of infer any string value in this case, we are no exception.
impl Display for CustomEnum {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str = match self {
CustomEnum::ValueA => { "Value A".to_string() },
};
write!(f, "{}", str)
}
}
#[derive(XmlSerializable)]
#[xml(name="object")]
struct XMLObject {
pub enum_field: CustomEnum,
}
// ...
println!(from_obj(&instance));
// ...
应产生
<object>
<enum_field>ValueA</enum_field>
</object>
无名称结构体
使用这样的单元结构体
#[derive(XmlSerializable)]
#[xml(ns="a", name="object")]
pub struct XMLObject(String);
应产生
<a:object>Some Text</a:object>
注意:在这种情况下不支持多个属性,并且会产生编译错误。
单元结构体
使用这样的单元结构体
#[derive(XmlSerializable)]
#[xml(name="object")]
struct XMLObject;
应产生
<object></object>
不如作为根元素有用...但考虑将其用作更树状上下文中的标志字段。
树
以这种方式组合结构体
#[derive(XmlSerializable)]
#[xml(name="my_child")]
struct Child {
pub child_field_a: String,
}
#[derive(XmlSerializable)]
#[xml(name="object", case="Camel")]
struct XMLObject {
pub field_a: String,
#[xml(tree)] //Same as #[xml(flatten)]
pub child: Child
}
应产生
<object>
<fieldA>Some value</fieldA>
<my_child>
<child_field_a>Other value</child_field_a>
</my_child>
</object>
注意:大小写的作用域为元素。命名空间也是如此。
集合
以这种方式组合结构体
#[derive(XmlSerializable)]
#[xml(name="my_child")]
struct Child {
pub child_field_a: String,
}
#[derive(XmlSerializable)]
#[xml(name="object", case="Camel")]
struct XMLObject {
pub field_a: String,
pub children: Vec<Child>
}
应产生
<object>
<fieldA>Some Text</fieldA>
<children>
<my_child>
<child_field_a>Child A</child_field_a>
</my_child>
<my_child>
<child_field_a>Child B</child_field_a>
</my_child>
</children>
</object>
注意:也支持
HashMap<String, T: XmlSerializable>
,但没有命名效果。
结构体作为标签
配置嵌套结构体如下
#[derive(XmlSerializable)]
#[xml(tag, name="child")]
struct Child {
#[xml(attribute, name="attr")]
pub attribute: String,
#[xml(value)]
pub value: String,
}
#[derive(XmlSerializable)]
#[xml(name="object", case="Camel")]
struct XMLObject {
pub field_a: String,
#[xml(tree)]
pub child: Child
}
应产生
<object>
<fieldA>Some value</fieldA>
<child attr="Attr Value">Other value</child>
</object>
注意1:您可以有尽可能多的属性,但只有一个值!注意2:如果未指定,字段的默认行为是属性,值为空。
XML声明
您可以这样配置XML
#[derive(XmlSerializable)]
#[declaration(version="1.0" encoding="UTF-8" standaline = "no")]
#[xml(name="xml")]
struct XMLObject {
//...
}
// or
#[derive(XmlSerializable)]
#[declaration]
#[xml(name="xml")]
struct XMLObject {
//...
}
应产生
<?xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
<xml>
...
</xml>
注意:如果未指定,默认声明将使用
version="1.0" encoding="UTF-8" standaline = "no"
DTD
使用这个
#[derive(XmlSerializable)]
#[declaration]
#[dtd = "Note.dtd"]
#[xml(name="xml")]
struct XMLObject {
//...
}
应产生
<?xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
<!DOCTYPE xml SYSTEM "Note.dtd">
<xml>
...
</xml>
注意1:目前不支持内联DTD。但是,我愿意探索替代方法。欢迎提交拉取请求,并将受到欢迎和欣赏。注意2:XML验证不在本项目的范围内。
PI(处理指令)
使用这个
#[derive(XmlSerializable)]
#[declaration]
#[pi(something key="value" flag)]
#[xml(name="xml")]
struct XMLObject {
//...
}
应产生
<?xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
<?something key="value" flag?>
<xml>
...
</xml>
便利性
CDATA
这个
println!(cdata!("Some text & others"));
打印这个
<![CDATA[Some text & others]]>
文本编码
println!(encode!("Some text & others"));
打印这个
Some text & others
注释
这个
println!(comment!("Some text & others"));
打印这个
<!--Some text & others-->
反序列化
从简单开始
这是可能的简单示例
#[derive(XmlDeserializable)]
struct XMLObject {
pub some_string: String,
pub some_int: i32,
pub some_float: f32
}
// ...
let xml = r#"
<XMLObject>
<some_string>Some Content A</some_string>
<some_int>0</some_int>
<some_float>0.0</some_float>
</XMLObject>"#
let instance: XMLObject = from_xml(&xml)?;
assert_eq!(instance.some_string, "Some Content A");
assert_eq!(instance.some_int, 0);
assert_eq!(instance.some_float, 0.0);
// ...
如您所见,这和序列化中的标签结构相同。请查看大量的示例 这里!
名称、属性、枚举、无名称结构体、单元结构体、树、集合以及结构体作为标签
与序列化完全一样,但方向相反。相同的标签!😊
便利性
XML声明
可以使用此宏解析声明!
let (version, encoding, standalone) = declaration!(&xml);
DTD
可以使用此宏解析DTD!
let (target, file) = dtd!(&xml);
PI(处理指令)
可以使用此宏解析PI!
instructions!(&xml, | tag, instruction, params | {
// DO something related with the instruction itself
});
文本解码
println!(decode!("Some text & others"));
打印这个
Some text & others
命名空间
将作为正常标签属性可用。
错误
Xavier DOM(WIP)实现使用 DOMException
,因为规范,但 "Xavier DeSer tiene un PError" ʕ•ᴥ•ʔ
待办事项
具有生命周期和其他的结构的结构体
难度:简单
deserialize::parser::complex::tokens::types
中的TypeParser函数以静态结构化方式处理类型解析,期望元素遵循预定义的顺序。虽然这种方法对简单的Rust元素非常有效,但在处理更复杂的Rust结构时可能需要更多的时间和努力。然而,这项任务是可以管理的,通过仔细的关注,我们可以有效地处理这些复杂性。
如有必要,您可以在constructors.rs
中修改对象创建过程,或在setters/
中调整结构字段赋值。
实现DOM
难度:中等
(branch feature/dom
)
规范来自https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html。
DOM实现必须通过名为"dom"
的Cargo功能来访问,可以使用以下方式
//...
let doc = to_dom(&xml);
//...
let xml = from_dom(&xml);
//...