Rust XML处理库sxd-document的使用,高效解析与操作XML文档的Rust插件库

Rust XML处理库sxd-document的使用,高效解析与操作XML文档的Rust插件库

SXD-Document

一个用Rust编写的XML库。

概述

该项目目前分为两个crate:

  1. document - 基本的DOM操作和从字符串读取/写入XML。
  2. xpath - XPath 1.0表达式的实现。

还有一些用于在命令行进行实验的分散实用工具。

未来,我希望能添加对XSLT 1.0的支持。

目标

这个项目有两个目标,一个比另一个更容易实现:

  1. 帮助我学习Rust。
  2. 替换libxml和libxslt。

贡献

  1. Fork它
  2. 创建你的特性分支(git checkout -b my-new-feature
  3. 添加一个失败的测试。
  4. 添加代码以通过测试。
  5. 提交你的更改(git commit -am 'Add some feature'
  6. 确保测试通过。
  7. 推送到分支(git push origin my-new-feature
  8. 创建一个新的Pull Request

安装

运行以下命令将全局安装二进制文件:

cargo install sxd-document

作为库安装

在你的项目目录中运行以下Cargo命令:

cargo add sxd-document

或者将以下行添加到你的Cargo.toml中:

sxd-document = "0.3.2"

完整示例代码

use sxd_document::parser;
use sxd_document::dom::Document;

fn main() {
    // 示例XML字符串
    let xml_content = r#"
        <books>
            <book id="1">
                <title>Rust Programming</title>
                <author>John Doe</author>
                <year>2023</year>
            </book>
            <book id="2">
                <title>XML Processing in Rust</title>
                <author>Jane Smith</author>
                <year>2023</year>
            </book>
        </books>
    "#;

    // 解析XML文档
    let package = parser::parse(xml_content).expect("Failed to parse XML");
    let document = package.as_document();

    // 获取根元素
    let root = document.root();
    let books_element = root.children()
        .find(|c| c.element().is_some_and(|e| e.name() == "books"))
        .and_then(|c| c.element())
        .expect("Could not find books element");

    // 遍历所有book元素
    for book in books_element.children().filter_map(|c| c.element()) {
        if book.name() == "book" {
            // 获取book的属性
            let id = book.attribute("id").unwrap_or("unknown");
            println!("Book ID: {}", id);

            // 获取子元素内容
            for child in book.children().filter_map(|c| c.element()) {
                match child.name().as_ref() {
                    "title" => println!("Title: {}", child.text()),
                    "author" => println!("Author: {}", child.text()),
                    "year" => println!("Year: {}", child.text()),
                    _ => {}
                }
            }
            println!("---");
        }
    }

    // 创建新的XML文档
    let new_document = Document::new();
    let root = new_document.create_element("library");
    new_document.set_root(root);

    // 添加新元素
    let book = new_document.create_element("book");
    book.set_attribute_value("id", "3");
    
    let title = new_document.create_element("title");
    title.append_text("New Rust Book");
    book.append_child(title);
    
    let author = new_document.create_element("author");
    author.append_text("New Author");
    book.append_child(author);
    
    root.append_child(book);

    // 输出生成的XML
    let writer = sxd_document::writer::format_document(&new_document);
    println!("Generated XML:\n{}", writer);
}

这个示例展示了如何使用sxd-document库来:

  1. 解析XML字符串
  2. 遍历XML文档结构
  3. 读取元素和属性
  4. 创建新的XML文档
  5. 添加元素和文本内容
  6. 格式化输出XML文档

要运行此代码,请确保在Cargo.toml中添加了sxd-document依赖:

[dependencies]
sxd-document = "0.3.2"

1 回复

sxd-document:Rust中的高效XML处理库

概述

sxd-document是一个专为Rust语言设计的XML文档处理库,提供了完整的XML解析、创建和操作功能。该库采用纯Rust实现,无需外部依赖,具有内存安全和零成本抽象的优势。

核心特性

  • 完整的XML 1.0规范支持
  • DOM风格的文档操作接口
  • 高性能的解析器实现
  • 类型安全的API设计
  • 支持命名空间处理

安装方法

在Cargo.toml中添加依赖:

[dependencies]
sxd-document = "0.3.2"

基本使用方法

1. 解析XML文档

use sxd_document::parser;

let xml_content = r#"<root><element attr="value">Text content</element></root>"#;
let package = parser::parse(xml_content).expect("Failed to parse XML");

let document = package.as_document();
let root = document.root().children()[0];

2. 创建新XML文档

use sxd_document::dom;

let package = dom::Package::new();
let document = package.as_document();

let root = document.create_element("root");
let element = document.create_element("child");
element.set_attribute_value("attribute", "value");

root.append_child(element);
document.append_child(root);

3. 遍历XML节点

fn traverse_nodes(node: dom::Node) {
    match node {
        dom::Node::Element(e) => {
            println!("Element: {}", e.name());
            for attr in e.attributes() {
                println!("  Attribute: {} = {}", attr.name(), attr.value());
            }
            for child in e.children() {
                traverse_nodes(child);
            }
        }
        dom::Node::Text(t) => {
            println!("Text: {}", t.text());
        }
        _ => {}
    }
}

4. 修改XML内容

let element = document.create_element("new_element");
element.set_attribute_value("new_attr", "new_value");

if let Some(parent) = document.root().children().first() {
    if let dom::Node::Element(e) = parent {
        e.append_child(element);
    }
}

5. 序列化为字符串

use sxd_document::writer::format_document;

let formatted_xml = format_document(&document);
println!("{}", formatted_xml);

高级用法示例

处理命名空间

let element = document.create_element_ns(
    "http://example.com/ns",
    "prefix:element"
);

XPath查询支持

use sxd_xpath::{Factory, Context};

let factory = Factory::new();
let xpath = factory.build("//element[@attr='value']").unwrap();
let context = Context::new();

let result = xpath.evaluate(&context, document.root()).unwrap();

性能建议

  • 对于大型XML文件,考虑使用流式解析
  • 重用Document和Package对象以减少内存分配
  • 使用XPath时预编译表达式

错误处理

match parser::parse(xml_content) {
    Ok(package) => {
        // 处理成功
    }
    Err(e) => {
        eprintln!("解析错误: {}", e);
    }
}

sxd-document提供了强大而灵活的XML处理能力,适合各种规模的XML文档操作需求。

完整示例demo

use sxd_document::{dom, parser};
use sxd_document::writer::format_document;

fn main() {
    // 示例1: 解析XML文档
    println!("=== 解析XML文档示例 ===");
    let xml_content = r#"<books>
        <book id="1">
            <title>Rust编程语言</title>
            <author>Steve Klabnik</author>
        </book>
        <book id="2">
            <title>Rust实战</title>
            <author>Tim McNamara</author>
        </book>
    </books>"#;
    
    let package = parser::parse(xml_content).expect("解析XML失败");
    let document = package.as_document();
    
    // 示例2: 遍历XML节点
    println!("\n=== 遍历XML节点示例 ===");
    if let Some(root) = document.root().children().first() {
        traverse_nodes(root);
    }
    
    // 示例3: 创建新XML文档
    println!("\n=== 创建新XML文档示例 ===");
    let new_package = dom::Package::new();
    let new_document = new_package.as_document();
    
    // 创建根元素
    let library = new_document.create_element("library");
    
    // 创建第一个书籍元素
    let book1 = new_document.create_element("book");
    book1.set_attribute_value("id", "101");
    
    let title1 = new_document.create_element("title");
    let title_text1 = new_document.create_text("深入理解Rust");
    title1.append_child(title_text1);
    
    let author1 = new_document.create_element("author");
    let author_text1 = new_document.create_text("Carol Nichols");
    author1.append_child(author_text1);
    
    book1.append_child(title1);
    book1.append_child(author1);
    
    // 创建第二个书籍元素
    let book2 = new_document.create_element("book");
    book2.set_attribute_value("id", "102");
    
    let title2 = new_document.create_element("title");
    let title_text2 = new_document.create_text("Rust系统编程");
    title2.append_child(title_text2);
    
    let author2 = new_document.create_element("author");
    let author_text2 = new_document.create_text("Jim Blandy");
    author2.append_child(author_text2);
    
    book2.append_child(title2);
    book2.append_child(author2);
    
    // 将书籍添加到图书馆
    library.append_child(book1);
    library.append_child(book2);
    new_document.append_child(library);
    
    // 示例4: 序列化为字符串
    println!("\n=== 序列化XML文档示例 ===");
    let formatted_xml = format_document(&new_document);
    println!("{}", formatted_xml);
    
    // 示例5: 错误处理
    println!("\n=== 错误处理示例 ===");
    let invalid_xml = r#"<root><unclosed_element>"#;
    match parser::parse(invalid_xml) {
        Ok(_) => println!("XML解析成功"),
        Err(e) => println!("XML解析错误: {}", e),
    }
}

// 递归遍历XML节点的函数
fn traverse_nodes(node: sxd_document::dom::Node) {
    match node {
        sxd_document::dom::Node::Element(e) => {
            println!("发现元素: {}", e.name());
            
            // 输出所有属性
            for attr in e.attributes() {
                println!("  属性: {} = {}", attr.name(), attr.value());
            }
            
            // 递归遍历子节点
            for child in e.children() {
                traverse_nodes(child);
            }
        }
        sxd_document::dom::Node::Text(t) => {
            let text = t.text().trim();
            if !text.is_empty() {
                println!("文本内容: {}", text);
            }
        }
        sxd_document::dom::Node::Comment(c) => {
            println!("注释: {}", c.text());
        }
        _ => {} // 忽略其他类型的节点
    }
}

这个完整示例展示了sxd-document库的主要功能:

  1. 解析现有的XML文档
  2. 遍历和访问XML节点及其属性
  3. 创建新的XML文档结构
  4. 添加元素、属性和文本内容
  5. 将文档序列化为字符串格式
  6. 处理解析过程中可能出现的错误

每个功能都配有详细的注释说明,帮助理解代码的作用和使用方法。

回到顶部