Сохранение HTML-тегов в значениях дочерних узлов XML при использовании XmlSerializer

#javascript #html #xml #blob #domparser

#javascript #HTML #xml #Большой двоичный объект #domparser

Вопрос:

Я работаю с API blob-объектов в последней версии Chrome и хотел бы, чтобы следующий XML DOM был добавлен к новому пустому URL-адресу объекта:

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

Этот фрагмент XML выбирается пользователем с помощью мыши из редактируемого содержимого DIV. Затем я преобразую этот выбор в 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 не может преобразовать в XML любые узлы, в которых были бы какие-либо теги HTML, что приводит к следующему 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, "amp;<");//replace the "<" with "amp;<"
var encoded_title = encoded_title_lt.replace(/>/g, "amp;>");//replace the ">" with "amp;>"
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-теги в пользовательском вводе, готовые для передачи в api blob?

Комментарии:

1.Не могли бы вы уточнить, каким именно window.getSelection().toString() должно быть содержимое сейчас? Вы сказали, что пользователь выбрал весь (?) XML, который вы показали, но тогда я не понимаю, как было бы разумно, если бы вы обернули его дополнительным root .

2. И в какой версии HTML вы помещаете H2 элементы or BR в Title элемент? Разве title обычный текст не является дочерним элементом head only?

3. @MartinHonnen Я предполагаю, что это XML, который может содержать теги HTML, но он не должен быть HTML сам по себе.

4. Строковое значение <root><Title><H1>A Title</H1><H2>A Subtitle</H2>Some text or other elements<BR/></Title></root> анализируется абсолютно нормально для меня в Chrome и дает именно тот результат, который можно было бы ожидать — jsfiddle.net/53a6bed0 На самом деле не уверен, в чем на самом деле заключается проблема.

5. «Проблема в том, что DOMParser не обрабатывает узлы, содержащие теги HTML» — вы так говорите , но я понятия не имею, что это на самом деле должно означать. Объясните, что не так с результатом, который я показал, или объясните, как ваш реальный сценарий на самом деле значительно отличается от того, что происходит там.

Ответ №1:

Ваша проблема заключается в getSelection().toString() том, что это вернет текстовое содержимое фактического выбора. То, что вы хотите Range.cloneContents() , — это получить копию структуры DOM:

 document.querySelector("button").onclick = evt => {
const sel = getSelection();
const range = sel.rangeCount amp;amp; 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>