CDATA внутри обработки PCDATA в XML

Если у нас есть следующий элемент XML:

<x>a &lt; b</x>

и еще один

<y>a<![CDATA[ < ]]>b</y>

Имеют ли оба элемента x и y значение a < b? Является ли второй пример допустимым, распространенным, рекомендуемым или что-то в этом роде?

AFAK y имеет три дочерних элемента — PCDATA a, CDATA < и PCDATA b и некоторые библиотеки разбирают его именно так. С другой стороны, https://pugixml.org/ for one возвращает только a в качестве значения для x (вспомогательная функция) .


person Doncho Gunchev    schedule 30.10.2020    source источник


Ответы (1)


Между ними есть принципиальная разница:

CDATA означает Символьные данные, а PCDATA означает Проанализированные символьные данные, что уже дает нам подсказку в правильном направлении. почему парсеры могут вести себя по-разному, в зависимости от их уровня соответствия.

Разделы CDATA являются строгими и чистыми экранами всего, что находится между тегами <![CDATA[ и ]]>. Ничто из того, что здесь написано, не должно вообще анализироваться XML-процессором! Соответствующий синтаксический анализатор XML просто игнорирует что-либо здесь и незаметно передает это любому приложению, запросившему XML (которое затем может обрабатывать его самостоятельно). Вот почему мы можем поместить сюда любые данные с подстановочными символами, при этом XML не станет недействительным.

&lt; – это Сущность, а точнее Сущность персонажа. Сущности — это «заполнители» или «маркеры», которые заменяются содержимым. Это означает, что объект также является PCDATA (Parsed Character DATA). Он анализируется синтаксическим анализатором XML, который затем интерпретирует его (пытается разрешить его содержимое), чтобы он мог заменить им сущность.

Что касается значения данных, нам может потребоваться дополнительная информация о приложении, которое запрашивает XML. В области инструментов обработки XML (XSD, XSLT, XPath, XQuery и т. д.) в обоих случаях он должен получиться как любой из типов данных XPath text(), xs:string() или xs:untypedAtomic, в зависимости от того, какую функцию вы использовали для получения доступ к нему. Например:

let $t := <xml>Text <![CDATA[test]]> bla.</xml>
return $t/data() instance of xs:untypedAtomic
let $t := <xml>Text <![CDATA[test]]> bla.</xml>
return $t/string() instance of xs:string
let $t := <xml>Text <![CDATA[test]]> bla.</xml>
return $t/text() instance of text()

все приводят к true.

Однако для любого приложения, которое не работает с моделью данных XML, результатом должен быть просто текст, который находится между тегами элемента.

Здесь есть интересное примечание и целая ветка по этому поводу, и похожие темы.

person amix    schedule 31.10.2020
comment
Я понимаю разницу между CDATA и PCDATA, мой вопрос больше о том, как с этим справиться - должен ли я написать вспомогательную функцию, которая объединяет все дочерние элементы CDATA и PCDATA элемента в большую строку, или просто использовать первый (например, pugixml, который вернет a как значение y) или отклонит элемент как недопустимый или неподдерживаемый или что-то в этом роде. - person Doncho Gunchev; 01.11.2020
comment
Для всего, что находится за пределами домена XML, оба выражают одно и то же: a < b. Поскольку я не понимаю, каков ваш желаемый результат (что вы делаете с данными, которые вы получаете из XML), я не могу ничего порекомендовать. Хотя в обычных случаях я бы просто присоединил строковые значения. - person amix; 02.11.2020