31 个版本 (19 个破坏性更新)
0.20.0 | 2024 年 5 月 23 日 |
---|---|
0.19.0 | 2023 年 11 月 18 日 |
0.18.1 | 2023 年 9 月 30 日 |
0.18.0 | 2023 年 2 月 4 日 |
0.3.0 | 2018 年 10 月 29 日 |
#11 in 解析器实现
每月 441,339 次下载
用于 1,101 个 crate (148 直接使用)
165KB
4K SLoC
roxmltree
将 XML 文档表示为只读树。
// Find element by id.
let doc = roxmltree::Document::parse("<rect id='rect1'/>")?;
let elem = doc.descendants().find(|n| n.attribute("id") == Some("rect1"))?;
assert!(elem.has_tag_name("rect"));
为什么是只读的?
因为在某些情况下,你可能只需要从 XML 文档中检索一些数据。对于这种情况,我们可以进行很多优化。
解析行为
遗憾的是,XML 可以以多种不同的方式解析。 roxmltree 尝试模仿 Python 的 lxml 的行为。更多详细信息,请参阅 docs/parsing.md。
替代方案
功能/包 | roxmltree | libxml2 | xmltree | sxd-document |
---|---|---|---|---|
元素命名空间解析 | ✓ | ✓ | ✓ | ~1 |
属性命名空间解析 | ✓ | ✓ | ✓ | |
实体引用 | ✓ | ✓ | × | × |
字符引用 | ✓ | ✓ | ✓ | ✓ |
属性-值规范化 | ✓ | ✓ | ||
注释 | ✓ | ✓ | ✓ | |
处理指令 | ✓ | ✓ | ✓ | ✓ |
UTF-8 BOM | ✓ | ✓ | × | × |
非 UTF-8 输入 | ✓ | |||
完全 DTD 支持 | ✓ | |||
位置保留2 | ✓ | ✓ | ||
HTML 支持 | ✓ | |||
树修改 | ✓ | ✓ | ✓ | |
写入 | ✓ | ✓ | ✓ | |
无 unsafe | ✓ | ✓ | ||
语言 | Rust | C | Rust | Rust |
依赖项 | 0 | - | 2 | 2 |
测试版本 | 0.20.0 | Apple 提供的 | 0.10.3 | 0.3.2 |
许可 | MIT / Apache-2.0 | MIT | MIT | MIT |
图例
- ✓ - 支持
- × - 解析错误
- ~ - 部分支持
- nothing - 不支持
说明
- 无默认命名空间传播。
- roxmltree 保持所有节点和属性在原始文档中的位置,因此如果你需要,可以轻松检索它。有关详细信息,请参阅 examples/print_pos.rs。
还有 elementtree
和 treexml
包,但它们已经废弃很长时间了。
性能
以下是一些将 roxmltree
与其他 XML 树库进行比较的基准测试。
test huge_roxmltree ... bench: 2,997,887 ns/iter (+/- 48,976)
test huge_libxml2 ... bench: 6,850,666 ns/iter (+/- 306,180)
test huge_sdx_document ... bench: 9,440,412 ns/iter (+/- 117,106)
test huge_xmltree ... bench: 41,662,316 ns/iter (+/- 850,360)
test large_roxmltree ... bench: 1,494,886 ns/iter (+/- 30,384)
test large_libxml2 ... bench: 3,250,606 ns/iter (+/- 140,201)
test large_sdx_document ... bench: 4,242,162 ns/iter (+/- 99,740)
test large_xmltree ... bench: 13,980,228 ns/iter (+/- 229,363)
test medium_roxmltree ... bench: 421,137 ns/iter (+/- 13,855)
test medium_libxml2 ... bench: 950,984 ns/iter (+/- 34,099)
test medium_sdx_document ... bench: 1,618,270 ns/iter (+/- 23,466)
test medium_xmltree ... bench: 4,315,974 ns/iter (+/- 31,849)
test tiny_roxmltree ... bench: 2,522 ns/iter (+/- 31)
test tiny_libxml2 ... bench: 8,931 ns/iter (+/- 235)
test tiny_sdx_document ... bench: 11,658 ns/iter (+/- 82)
test tiny_xmltree ... bench: 20,215 ns/iter (+/- 303)
与流式XML解析器相比,roxmltree
的速度略慢于 quick-xml
,但仍然比 xmlrs
快得多。请注意,流式解析器通常不提供适当的字符串转义、DTD解析和命名空间支持。
test huge_quick_xml ... bench: 2,997,887 ns/iter (+/- 48,976)
test huge_roxmltree ... bench: 3,147,424 ns/iter (+/- 49,153)
test huge_xmlrs ... bench: 36,258,312 ns/iter (+/- 180,438)
test large_quick_xml ... bench: 1,250,053 ns/iter (+/- 21,943)
test large_roxmltree ... bench: 1,494,886 ns/iter (+/- 30,384)
test large_xmlrs ... bench: 11,239,516 ns/iter (+/- 76,937)
test medium_quick_xml ... bench: 206,232 ns/iter (+/- 2,157)
test medium_roxmltree ... bench: 421,137 ns/iter (+/- 13,855)
test medium_xmlrs ... bench: 3,975,916 ns/iter (+/- 44,967)
test tiny_quick_xml ... bench: 2,233 ns/iter (+/- 70)
test tiny_roxmltree ... bench: 2,522 ns/iter (+/- 31)
test tiny_xmlrs ... bench: 17,155 ns/iter (+/- 429)
说明
基准测试是在 Apple M1 Pro 上进行的。您可以在 benches
目录中运行 cargo bench
来尝试运行基准测试。
- 由于所有库都提供了不同的XML支持,因此基准测试有点没有意义。
- 我们使用 rust-libxml 包装器crate对 libxml2 进行基准测试。
内存开销
roxmltree
尽可能使用最少的内存来允许解析非常大的(多GB)XML文件。
峰值内存使用量并不直接与文件大小相关,而是与文件中的节点和属性的数量相关。需要归一化(即分配)多少个属性。以及需要预处理的(即分配的)文本节点有多少。
roxmltree
从不分配元素和属性名称、处理指令和注释。
通过禁用 positions
功能,您可以为每个节点和属性节省8个字节。
平均而言,开销约为文件大小的6-8倍。例如,我们的1.1GB样本XML文件,在默认功能启用的情况下,峰值内存使用量为7.6GB RAM,当禁用 positions
时,内存使用量为6.8GB RAM。
安全性
- 此库不能崩溃。任何崩溃都应被视为严重错误并报告。
- 此库禁止
unsafe
代码。
API
此库使用基于迭代器的Rust惯用API。如果您更熟悉浏览器/JS DOM API,您可以查看 tests/dom-api.rs 以了解它如何映射到Rust API。
许可
许可为以下任一项
任选其一。
贡献
除非您明确表示,否则根据Apache-2.0许可证定义的,您有意提交的任何贡献,均应按上述方式双重许可,不得附加任何额外条款或条件。