php / php/php-src

Dom\HTMLDocument: Impossible to add text node on document level

未关闭
#23,562 4 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Feature Status: Needs Triage
主要语言
C
星标
40.4k
派生
8.1k
平均合并
2 天 13 小时
30 天内合并 PR
96

描述

Description

The following code...

$doc = \Dom\HTMLDocument::createFromString('Hello <b>world</b>!',LIBXML_HTML_NOIMPLIED);
$greeting = $doc->firstChild;
echo get_class($greeting)."<br />";
$new_greeting = $doc->createTextNode('Welcome');
$greeting->replaceWith($new_greeting);
echo htmlentities($doc->saveHtml());

results in this error:

DOMException: Cannot insert text as a child of a document in Dom\CharacterData->replaceWith()

This is different behavior from the old DOM classes which allowed this. I understand, this spec-compliance is supposed to be a feature. If I understand correctly, the new Lexbor-based parser offers validity checks for some methods and not for others:

https://lexbor.com/modules/dom/

E.g. lxb_dom_node_insert_before_spec vs lxb_dom_node_insert_before etc.

I'm unaware of the current PHP implementation but I assume it is using the _spec versions throughout without any option to turn it off.

I think this is problematic. The NOIMPLIED option is very useful indeed if you want to handle document fragments etc. without unnecessary wrapper tags.

The above code leads to the peculiar situation that you can indeed create a Document with textNodes on the document level, but if you just want to replace that textNode with a different textNode it won't work. This complicates things a lot unnecessarily. Other methods like insertAdjacentHTML, appendChild etc are equally stubborn.

There are different solutions for this: IMHO the easiest one would be to use the non-spec versions of these functions if NOIMPLIED was specified. NOIMPLIED explicitly allows a non-spec document to be imported. Any manipulation should also be allowed then.

Another alternative would be to create a new general flag LIBXML_HTML_RELAX_SPEC.

A third alternative would be to specifically add option flags to the individual methods to allow this for a single call.

I'm unsure what's really the best solution but at the moment, porting over existing code is unnecessarily difficult due to this restriction and I really think this feature would make a lot of sense anyway. Thanks for considering.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先使用 Dom\HTMLDocument::createFromString、LIBXML_HTML_NOIMPLIED 和 CharacterData::replaceWith() 复现 PHP 代码片段。跟踪 replaceWith()、insertAdjacentHTML() 和 appendChild() 如何处理文档级文本节点,然后比较 issue 中提到的符合规范和不符合规范的 Lexbor 入口点。对于 NOIMPLIED 文档,在得出明确结论并实现或记录一致的行为,同时为所示案例添加测试后,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
c, php
领域
api, backend
Issue 类型
功能
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
48/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。