我需要查找并替换html片段中的一些标签,例如replace
<div class="not-replaced">
<i18n>Hello World</i18n>
</div>
与
<div class="not-replaced">
<span class="i18n" data-location="/index.html:$/i18n">Hello World</span>
</div>
我试图通过
html5ever
和markup5ever_rcdom
来实现这一点,我想我需要一个递归函数来遍历节点树,但我无法想出一个有效的函数,即创建新节点的函数的签名元素是 RcDom::create_element(&mut self)
,所以我的递归函数需要两个参数:
dom: &mut RcDom
或 mut dom: RcDom
使用 node: Rc<Node>
穿越这很困难,因为我无法传递像
self.traverse(&mut dom, dom.document)
这样的论点。
到目前为止我能找到的唯一有效签名是
fn traverse(&self, dom: &RcDom, node: &Rc<Node>)
,但它没有用,因为dom
不可变,我无法在其上调用create_element
。
这是我现在拥有的代码:
fn expand_macro(&mut self) {
let mut html = File::open("index.html").unwrap();
let mut dom = html5ever::parse_fragment(
RcDom::default(),
html5ever::ParseOpts::default(),
QualName::new(None, ns!(html), local_name!("div")),
vec![],
)
.from_utf8()
.read_from(&mut html)
.unwrap();
self.traverse(&mut dom, dom.document);
}
fn traverse(&mut self, dom: &mut RcDom, node: Rc<Node>) {
}
如何重写代码,这样我就可以访问
&mut RcDom
和 Rc<Node>
来遍历。
或其他一些建议来实现我在背景中描述的相同目标。
谢谢,非常感谢您的帮助!
这可以看作是一个“迭代时修改”的问题,我的解决方案是:
代码片段如下所示:
pub struct HtmlMacro {
pub location: String,
pub parent_node: Rc<Node>,
pub index: usize,
pub text: String,
}
fn expand_macro_html(source: String, source_path: &Path) -> String {
// parse dom
let mut dom = html5ever::parse_fragment(/* options */)
.from_utf8()
.one(source.as_bytes());
// the first iteration only needs a readonly reference to dom
// collect_html_macros(dom: &RcDom, file_path: &Path) -> Vec<HtmlMacro>
let macros = collect_html_macros(&dom, source_path);
// the second iteration has a mutable reference to dom
// expand macros
for m in macros {
let mut children = m.parent_node.children.borrow_mut();
let expanded_macro = dom.create_element(/* new element */);
children[m.index] = expanded_macro;
}
// serialize
// return serialized document
}