Как мне написать неэкранированный XML вне CDATA - PullRequest
8 голосов
/ 08 июня 2010

Я пытаюсь записать данные XML с помощью Stax, где само содержимое является HTML

Если я попытаюсь

xtw.writeStartElement("contents");
xtw.writeCharacters("<b>here</b>");
xtw.writeEndElement();

Я понял

<contents>&lt;b&gt;here&lt;/b&gt;</contents>

Затем я замечаю метод CDATA и изменяю свой код на:

xtw.writeStartElement("contents");
xtw.writeCData("<b>here</b>");
xtw.writeEndElement();

и на этот раз результат

<contents><![CDATA[<b>here</b>]]></contents>

что все еще не хорошо. Что я действительно хочу, так это

<contents><b>here</b></contents>

Так есть ли XML API / библиотека, которая позволяет мне писать необработанный текст, не находясь в разделе CDATA? До сих пор я смотрел на Stax и JDom, и, похоже, они этого не предлагают.

В конце я мог бы прибегнуть к старому доброму StringBuilder, но это было бы не элегантно.

Обновление:

Пока я согласен в основном с ответами. Однако вместо <b>here</b> я мог бы иметь HTML-документ объемом 1 МБ, который я хотел бы встроить в больший XML-документ. То, что вы предлагаете, означает, что я должен проанализировать этот HTML-документ, чтобы понять его структуру. Я хотел бы избежать этого, если это возможно.

Ответ:

Это невозможно, иначе вы можете создать недействительные документы XML.

Ответы [ 7 ]

3 голосов
/ 08 июня 2010

Проблема в том, что это не необработанный текст, а элемент, поэтому вы должны писать

xtw.writeStartElement("contents");
xtw.writeStartElement("b");
xtw.writeCData("here");
xtw.writeEndElement();
xtw.writeEndElement();
1 голос
/ 08 июня 2010

Если вы хотите, чтобы XML был включен как XML, а не как символьные данные, то в какой-то момент его нужно проанализировать. Если вы не хотите выполнять синтаксический анализ вручную, у вас есть две альтернативы:

(1) Использовать внешние анализируемые объекты - в этом случае внешний файл будет извлечен и проанализирован анализатором XML. Когда выходные данные снова сериализуются, они будут содержать содержимое внешнего файла.

[см. http://www.javacommerce.com/displaypage.jsp?name=entities.sql&id=18238]

(2) Использовать Xinclude - в этом случае файл должен запускаться через процессор xinclude, который объединит ссылки xinclude в вывод. Большинство процессоров xslt, а также xmllint также делают xinclude с соответствующей опцией.

[См .: http://www.xml.com/pub/a/2002/07/31/xinclude.html]

(XSLT также можно использовать для объединения документов без использования синтаксиса XInclude. XInclude просто предоставляет стандартный синтаксис)

0 голосов
/ 09 июня 2010

Если капля html на самом деле является xhtml, я бы предложил сделать что-то вроде (в псевдокоде):

xtw.writeStartElement("contents")
XMLReader  xtr=new XMLReader();
xtr.read(blob);
Dom dom=xtr.getDom();
for(element e:dom){
    xtw.writeElement(e);
}
xtw.writeEndElement();

или что-то в этом роде. Однажды мне пришлось сделать нечто подобное, но я использовал другую библиотеку.

0 голосов
/ 08 июня 2010

Я не вижу, в чем проблема с анализом большого блока XML, который вы хотите вставить в ваш вывод. Используйте синтаксический анализатор StAX для его анализа и просто напишите код для пересылки всех событий в существующий сериализатор (переменная "xtw").

0 голосов
/ 08 июня 2010

Если вы хотите встроить большой документ HTML в документ XML, тогда CDATA imho - это то, что вам нужно. Таким образом, вам не нужно понимать или обрабатывать внутреннюю структуру, и вы можете позже изменить тип документа с HTML на что-то другое без особых хлопот. Также Я думаю Вы не можете вставлять, например. Инструкции DOCTYPE напрямую (т.е. как структурированные данные, которые сохраняют семантику инструкции DOCTYPE). Они должны быть представлены в виде символов.

(Это в первую очередь ответ на ваше обновление, но, увы, мне не хватает представителя, чтобы комментировать ...............)

0 голосов
/ 08 июня 2010

Если ваши XML и HTML не слишком большие, вы можете обойти это:

xtw.writeStartElement("contents");
xtw.writeCharacters("anUniqueIdentifierForReplace"); // <--
xtw.writeEndElement();

Если у вас есть XML в виде строки:

xmlAsString.replace("anUniqueIdentifierForReplace", yourHtmlAsString);

Я знаю, это не так приятно, но это может сработать.


Изменить: Конечно, вы должны проверить, если yourHtmlAsString является действительным.

0 голосов
/ 08 июня 2010

Проблема не "здесь", это <b></b>.

Добавьте элемент <b> в качестве дочернего элемента содержимого, и вы сможете это сделать. Любая библиотека, такая как JDOM или DOM4J, позволит вам сделать это. Общий случай состоит в том, чтобы проанализировать содержимое в XML DOM и добавить корневой элемент как дочерний элемент <contents>.

Вы не можете добавить экранированные значения вне раздела CDATA.

...