【问题标题】:Preserve HTML Tags in XML Child Node Values While Using XMLSerializer使用 XMLSerializer 时在 XML 子节点值中保留 HTML 标记
【发布时间】:2022-01-14 07:23:50
【问题描述】:

我正在使用最新版 Chrome 中的 blob API,并希望将以下 XML DOM 添加到新的空对象 URL:

<root>
  <Title>
   <H1>A Title</H1>
   <H2>A Subtitle</H2>
   Some text or other elements<BR/>
  </Title>
</root>

用户用鼠标从内容可编辑的 DIV 中选择这段 XML。然后我将该选择转换为 XML DOM,如下所示:

var n_parser = new DOMParser; //new parser
var small_xml_string = "<root>" + window.getSelection().toString() + "</root>"; //add a root node
var small_xml_obj = n_parser.parseFromString(small_xml_string.replace(/\n/g, ""), "text/xml"); //convert user selection to string then to an XML DOM while removing some expected newlines below the selection

然而,DOMParser 无法将任何节点转换为其中包含任何 HTML 标记的 XML,从而导致以下 DOM:

<root>
  </Title>
</root>

我已经尝试转义 HTML 实体,但解析器的行为仍然相同。这是我为尝试处理实体而创建的代码:

var unencoded_title =
  small_xml_string.toString().substring(
    small_xml_string.toString().indexOf("<Title>") + 7,
    small_xml_string.toString().indexOf("</Title>")
    );//Find the string between the title tags
var encoded_title_lt = unencoded_title.replace(/</g, "&lt;");//replace the "<" with "&lt;"
var encoded_title = encoded_title_lt.replace(/>/g, "&gt;");//replace the ">" with "&gt;"
xml_dom.getElementsByTagName("Title")[0].childNodes[0].nodeValue = encoded_title //Add the encoded string to the node, replacing what's there

请注意,“xml_dom”是一个现成的 DOM,如下所示:

<root>
    <Title>Example
    </Title>
</root>

生成的 DOM 与我传入的 HTML 标记完全相同。 用户将在输入中添加 HTML 标记,例如换行符和上标。如何处理用户输入中的 HTML 标签,准备好传递给 blob api?

【问题讨论】:

  • 你能澄清一下window.getSelection().toString()的内容现在应该是什么吗?您说用户选择了您显示的整个(?)XML,但是我不明白您将 additional root 包裹在它周围有什么意义。
  • 您在哪个 HTML 版本中将 H2BR 元素放入 Title 元素中? title 不只是 head 的纯文本子代吗?
  • @MartinHonnen 我猜是XML,它可以包含 HTML标签,但它本身并不意味着成为 HTML。跨度>
  • 字符串值 &lt;root&gt;&lt;Title&gt;&lt;H1&gt;A Title&lt;/H1&gt;&lt;H2&gt;A Subtitle&lt;/H2&gt;Some text or other elements&lt;BR/&gt;&lt;/Title&gt;&lt;/root&gt; 在 Chrome 中对我来说解析得非常好,并给出了人们所期望的结果 - jsfiddle.net/53a6bed0 真的不确定问题到底应该出在哪里。
  • “问题是 DOMParser 不处理包含 HTML 标记的节点” - 你 那,但我不知道是什么它实际上应该是这个意思。解释我展示的小提琴产生的结果有什么问题 - 或者解释你的真实场景实际上与那里发生的情况有什么显着不同。

标签: javascript html xml blob domparser


【解决方案1】:

您的问题在getSelection().toString() 这将返回实际选择的文本内容。你要的是Range.cloneContents(),它会得到一份DOM结构的副本:

document.querySelector("button").onclick = evt => {
const sel = getSelection();
const range = sel.rangeCount && sel.getRangeAt(0);
const content = range.cloneContents?.();
const xml = new DOMParser().parseFromString(`<root>
  <Title/>
</root>`, "text/xml");
xml.querySelector("Title").append(content||"");
console.log(new XMLSerializer().serializeToString(xml));
};
Select the content below:
<H1>A Title</H1>
<H2>A Subtitle</H2>
Some text or other elements<BR/>
<button>log</button>

【讨论】: