Rust HTML解析库swc_html_parser的使用,高性能HTML解析与AST转换工具

Rust HTML解析库swc_html_parser的使用,高性能HTML解析与AST转换工具

安装

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

cargo add swc_html_parser

或者在Cargo.toml中添加以下行:

swc_html_parser = "14.0.0"

基本使用示例

以下是使用swc_html_parser解析HTML文档的基本示例:

use swc_html_parser::{
    parser::{Parser, ParserConfig},
    tokenizer::Tokenizer,
};

fn main() {
    // 示例HTML文档
    let html = r#"<!DOCTYPE html>
<html>
<head>
    <title>Test Page</title>
</head>
<body>
    <h1>Hello, world!</h1>
    <div class="container">
        <p>This is a paragraph.</p>
    </div>
</body>
</html>"#;

    // 创建Tokenizer
    let mut tokenizer = Tokenizer::new(html);
    
    // 配置Parser
    let config = ParserConfig {
        ..Default::default()
    };
    
    // 创建Parser
    let mut parser = Parser::new(tokenizer, config);
    
    // 解析HTML文档
    match parser.parse_document() {
        Ok(document) => {
            println!("Successfully parsed HTML document");
            // 遍历文档节点
            for child in document.children {
                println!("Node: {:?}", child);
            }
        }
        Err(err) => {
            eprintln!("Failed to parse HTML: {:?}", err);
        }
    }
}

完整示例:解析和转换HTML

use swc_html_parser::{
    parser::{Parser, ParserConfig},
    tokenizer::Tokenizer,
    ast::*,
};

fn main() {
    // HTML文档
    let html = r#"<div id="main">
    <h1 class="title">Sample Page</h1>
    <p>Welcome to <span>Rust</span> HTML parsing!</p>
</div>"#;

    // 创建Tokenizer和Parser
    let mut tokenizer = Tokenizer::new(html);
    let config = ParserConfig::default();
    let mut parser = Parser::new(tokenizer, config);

    // 解析文档
    let document = parser.parse_document().expect("Failed to parse HTML");

    // 遍历文档并打印节点信息
    walk_nodes(&document.children);
}

// 递归遍历节点
fn walk_nodes(nodes: &[Node]) {
    for node in nodes {
        match node {
            Node::Element(element) => {
                println!("Element: {}", element.tag_name);
                println!("Attributes: {:?}", element.attributes);
                walk_nodes(&element.children);
            }
            Node::Text(text) => {
                println!("Text: {}", text.value);
            }
            Node::Comment(comment) => {
                println!("Comment: {}", comment.value);
            }
            Node::DocumentType(doctype) => {
                println!("Doctype: {:?}", doctype);
            }
            _ => println!("Other node: {:?}", node),
        }
    }
}

高级功能示例:修改AST

use swc_html_parser::{
    parser::{Parser, ParserConfig},
    tokenizer::Tokenizer,
    ast::*,
};

fn main() {
    // 输入HTML
    let html = r#"<div class="old-class">
    <p>Old content</p>
</div>"#;

    // 解析HTML
    let mut tokenizer = Tokenizer::new(html);
    let config = ParserConfig::default();
    let mut parser = Parser::new(tokenizer, config);
    let mut document = parser.parse_document().expect("Failed to parse HTML");

    // 修改AST
    for node in &mut document.children {
        if let Node::Element(element) = node {
            // 修改class属性
            for attr in &mut element.attributes {
                if attr.name == "class" {
                    attr.value = Some("new-class".into());
                }
            }
            
            // 修改子节点内容
            for child in &mut element.children {
                if let Node::Text(text) = child {
                    if text.value.contains("Old") {
                        text.value = "New content".into();
                    }
                }
            }
        }
    }

    // 打印修改后的HTML结构
    println!("Modified document: {:#?}", document);
}

元数据

  • 版本: 14.0.0
  • 发布日期: 24天前
  • 许可证: Apache-2.0
  • 大小: 84.6 KiB
  • Rust版本: 2021 edition

维护者

  • Donny/강동윤 (kdy1)
  • SWC Bot (swc-bot)

1 回复

Rust HTML解析库swc_html_parser使用指南

以下是基于提供的内容整理的完整示例demo,展示了swc_html_parser的主要功能:

use swc_html_parser::{
    lexer::Lexer,
    parser::{Parser, ParserConfig},
};
use swc_html_ast::*;
use swc_html_codegen::{
    writer::basic::{BasicHtmlWriter, BasicHtmlWriterConfig},
    CodeGenerator, CodegenConfig,
};

fn main() {
    // 示例HTML内容
    let html = r#"
        <!DOCTYPE html>
        <html>
        <head>
            <title>示例页面</title>
        </head>
        <body>
            <div class="content">
                <h1>欢迎使用swc_html_parser</h1>
                <p>这是一个Rust HTML解析库</p>
                <a href="https://example.com">示例链接</a>
                <!-- 这是一条注释 -->
            </div>
        </body>
        </html>
    "#;

    // 1. 基本解析示例
    println!("=== 基本解析示例 ===");
    basic_parse(html);
    
    // 2. 遍历AST节点示例
    println!("\n=== 遍历AST节点示例 ===");
    let document = parse_document(html);
    walk_nodes(&document.children);
    
    // 3. 提取链接示例
    println!("\n=== 提取链接示例 ===");
    let links = extract_links(&document);
    println!("找到的链接: {:?}", links);
    
    // 4. AST序列化回HTML
    println!("\n=== AST序列化回HTML ===");
    let regenerated_html = serialize_to_html(&document);
    println!("重新生成的HTML:\n{}", regenerated_html);
}

/// 基本解析函数
fn basic_parse(html: &str) {
    let lexer = Lexer::new(html);
    let mut parser = Parser::new(lexer, ParserConfig::default());
    
    match parser.parse_document() {
        Ok(document) => println!("解析成功,获得 {} 个子节点", document.children.len()),
        Err(e) => eprintln!("解析错误: {:?}", e),
    }
}

/// 解析HTML文档
fn parse_document(html: &str) -> Document {
    let lexer = Lexer::new(html);
    let mut parser = Parser::new(lexer, ParserConfig::default());
    parser.parse_document().expect("解析HTML失败")
}

/// 遍历AST节点
fn walk_nodes(nodes: &[Node]) {
    for node in nodes {
        match node {
            Node::DocumentType(doctype) => {
                println!("文档类型: {}", doctype.name.as_deref().unwrap_or(""));
            }
            Node::Element(element) => {
                println!("元素: <{}>", element.tag_name);
                // 打印属性
                for attr in &element.attributes {
                    println!("  属性: {}={:?}", attr.name, attr.value);
                }
                // 递归处理子节点
                walk_nodes(&element.children);
            }
            Node::Text(text) => {
                println!("文本内容: {}", text.value.trim());
            }
            Node::Comment(comment) => {
                println!("注释: {}", comment.data);
            }
            _ => {}
        }
    }
}

/// 提取所有链接
fn extract_links(document: &Document) -> Vec<String> {
    let mut links = Vec::new();
    
    for node in &document.children {
        if let Node::Element(element) = node {
            if element.tag_name.to_lowercase() == "a" {
                for attr in &element.attributes {
                    if attr.name.to_lowercase() == "href" {
                        if let Some(value) = &attr.value {
                            links.push(value.to_string());
                        }
                    }
                }
            }
        }
    }
    
    links
}

/// 将AST序列化回HTML
fn serialize_to_html(document: &Document) -> String {
    let codegen_config = CodegenConfig {
        minify: false,
        ..Default::default()
    };

    let mut html_writer = BasicHtmlWriter::new(BasicHtmlWriterConfig::default());
    let mut code_generator = CodeGenerator::new(&mut html_writer, codegen_config);

    code_generator.generate(document).expect("生成HTML失败");
    html_writer.into_inner().to_string()
}

这个完整示例展示了swc_html_parser的主要功能:

  1. 基本HTML解析功能
  2. AST节点的遍历和检查
  3. 从HTML中提取特定信息(链接)
  4. 将AST重新序列化为HTML

示例中包含了详细的注释,解释了每个步骤的功能。要运行此代码,请确保按照前面提到的在Cargo.toml中添加了swc_html_parser依赖。

这个示例演示了如何在实际项目中使用swc_html_parser进行HTML处理,包括解析、分析和重新生成HTML文档。

回到顶部