11

Dashのドキュメントセットを生成するために、Web ページを解析し、特定の位置にアンカーを挿入し、変更された DOM を再度レンダリングしたいと考えています。これは可能ですか?

RcDomhtml5ever に含まれている例から、HTML ファイルを読み込んで貧弱な HTML 出力を行う方法はわかりますが、取得したオブジェクトを変更する方法がわかりません。

<a name="foo"></a>アンカー要素 ( ) を に挿入するスニペットを見たいと思いRcDomます。

注: これは特に Rust と html5ever に関する質問です...他の言語またはより単純な HTML パーサーでそれを行う方法を知っています。

4

1 に答える 1

15

ドキュメントを解析し、リンクにアンカーを追加し、新しいドキュメントを印刷するコードを次に示します。

extern crate html5ever;

use html5ever::{ParseOpts, parse_document};
use html5ever::tree_builder::TreeBuilderOpts;
use html5ever::rcdom::RcDom;
use html5ever::rcdom::NodeEnum::Element;
use html5ever::serialize::{SerializeOpts, serialize};
use html5ever::tendril::TendrilSink;

fn main() {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts {
            drop_doctype: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let data = "<!DOCTYPE html><html><body><a href=\"foo\"></a></body></html>".to_string();
    let dom = parse_document(RcDom::default(), opts)
        .from_utf8()
        .read_from(&mut data.as_bytes())
        .unwrap();

    let document = dom.document.borrow();
    let html = document.children[0].borrow();
    let body = html.children[1].borrow(); // Implicit head element at children[0].

    {
        let mut a = body.children[0].borrow_mut();
        if let Element(_, _, ref mut attributes) = a.node {
            attributes[0].value.push_tendril(&From::from("#anchor"));
        }
    }

    let mut bytes = vec![];
    serialize(&mut bytes, &dom.document, SerializeOpts::default()).unwrap();
    let result = String::from_utf8(bytes).unwrap();
    println!("{}", result);
}

これにより、次のように出力されます。

<html><head></head><body><a href="foo#anchor"></a></body></html>

childrenご覧のとおり、属性を介して子ノードをナビゲートできます。

そして、 の属性のベクトルに存在する属性を変更できますElement

于 2016-08-09T22:42:13.020 に答える