Как мне прочитать отдельные узлы xml с узла, который содержит как CDATA, так и xml

У меня проблема. У меня есть несколько файлов xml, которые случайным образом содержат узлы с узлами CDATA и reqular xml внутри. мне нужно прочитать содержимое этих узлов, но я не уверен, как определить, является ли узел обычным узлом xml, узлом CDATA или узлом, содержащим смесь обоих, где часть CDATA в начале и в конце может содержать что-либо. (я использую xPath для ссылки на свои узлы, если это помогает)

строка, используемая для получения текстового содержимого узла:

contentObj.text = contentNode.selectSingleNode("./text").text;

Пример xml, вызывающего проблему:

<text>
     <![CDATA[<P align=center>&nbsp;</P>
          <P align=center>]]>
     <media identifier="005896523">
          <label>
               <![CDATA[NOTE]]>
          </label>
          <description>
               <![CDATA[Image for NOTE]]>
          </description>
          <comments>Update Required</comments>
     </media>
    <![CDATA[</P>
       <P>&nbsp;</P>
       <P align=left>&nbsp;</P>]]>
</text>

person Reahreic    schedule 08.10.2012    source источник
comment
CDATA — это еще один способ цитирования текста. Он всегда является частью текстового узла.   -  person choroba    schedule 09.10.2012
comment
Я понимаю, что CDATA прозрачен, тогда я вызываю node.text, однако в приведенном выше xml, если я вызываю node.text, я получаю не только первые 2 строки, содержащиеся в cdata, но и текстовое значение любого узла, отличного от CDATA. Мне нужно иметь возможность разделить смесь CDATA XML CDATA в этом примере или, по крайней мере, определить, что узел содержит CDATA, чего не может быть в других итерациях полной структуры XML.   -  person Reahreic    schedule 09.10.2012
comment
Вы не можете отличить раздел CDATA от окружающего его текста. Если есть что-то (элемент) между ними, вы можете. Для какого узла вы вызываете node.text? Обратите внимание, что XPath может возвращать список узлов, если имеется несколько текстовых узлов.   -  person choroba    schedule 09.10.2012
comment
Я использую следующую строку для чтения содержимого узла ‹text›. contentObj.text = contentNode.selectSingleNode(./text).text; Он извлекает текст, инкапсулированный в разделе CDATA текстового узла, однако по какой-то неизвестной причине в том же узле есть другие узлы xml, однако они не находятся внутри раздела cdata.   -  person Reahreic    schedule 09.10.2012
comment
Что возвращают (./text/text())[1], (./text/text())[2] и т. д.?   -  person choroba    schedule 09.10.2012
comment
Первый возвращает несколько сотен строк текста из проанализированного xml-файла. Второй возвращает ноль.   -  person Reahreic    schedule 09.10.2012
comment
@Reahreic: несколько сотен строк текста? Это вообще не соответствует примеру XML.   -  person LarsH    schedule 09.10.2012
comment
пример, который я показал, представляет собой урезанную версию, в которой есть 3-5 родительских узлов и несколько дочерних узлов в этом узле, а затем следуют другие одноуровневые узлы. это большой файл, остальную часть я успешно проанализировал, только когда часть, структурированная как указано выше, вызывает проблемы   -  person Reahreic    schedule 09.10.2012
comment
Рад, что вы смогли заставить это работать. См. новый раздел Изменить в моем ответе.   -  person LarsH    schedule 12.10.2012


Ответы (1)


Когда ты сказал

contentNode.selectSingleNode("./text")

это, конечно, возвращает узел элемента <text>; но когда вы затем попросите

.text

свойства, вы запрашиваете текстовое содержимое всего элемента <text>, которое представляет собой конкатенацию значений всех его дочерних текстовых узлов.

Если вы хотите выбрать один текстовый узел, попробуйте

contentNode.selectSingleNode("./text/text()[1]").text;

т.е. выберите первый дочерний текстовый узел элемента <text>, затем извлеките его свойство text. Это должно дать вам "<P align=center>&nbsp;</P> <P align=center>" (как неразобранный текст, а не дерево XML) в вашем примере.

Чтобы отличить CDATA от не-CDATA, вам придется обойти XPath, который не предназначен для их различения. С другой стороны, XML DOM может, по крайней мере, в некоторых реализациях. Итак, вы можете попробовать

var children = contentNode.selectNodes("./text/node()");

который выберет nodeList всех дочерних элементов элемента <text>, включая текстовые узлы, узлы элементов и, возможно, узлы CDATA. Переберите узлы в children и проверьте их свойство nodeType, чтобы увидеть, является ли оно NODE_CDATA_SECTION, NODE_TEXT или чем-то другим.

Дайте нам знать, как это происходит, и нужна ли вам дополнительная помощь.

Редактировать

Исходя из того, что вы приняли этот ответ, я предполагаю, что вы смогли заставить все работать, и я рад, что вы смогли.

Тем не менее, я не хочу упускать это из виду, не подчеркнув предостережение, на которое намекал @choroba: оболочка CDATA (вокруг фрагмента текста) невидима для большинства инструментов XML (хотя текстовое содержимое видно). Модель данных XML (неформально описанная здесь) ничего не знает о разделах CDATA. Стандарт для XML Infoset явно опускает информацию о границах разделов, помеченных CDATA.

Таким образом, хотя на этот раз вам «повезло» в том, что вы использовали XML DOM, который действительно предоставляет информацию о разделах CDATA, это противоречит духу XML (и, следовательно, неразумно) полагаться на эту информацию для кодирования важных данных в XML. По этой причине вам было бы полезно закодировать эту информацию каким-либо другим способом. В противном случае, если вам когда-нибудь понадобится использовать другие XML-инструменты для данных, вы можете застрять.

Я думаю, что важной информацией, которую вы пытаетесь здесь извлечь, является тот факт, что текст в разделах CDATA является экранированной разметкой. Например. это части тегов HTML, которые не должны быть (или не могут быть) частью дерева XML. Таким образом, вы можете закодировать эту идентификацию, окружив каждую из них пользовательским элементом:

<text>
     <escaped><![CDATA[<P align=center>&nbsp;</P>
          <P align=center>]]></escaped>
     <media identifier="005896523">
     ...

Затем, чтобы найти эти разделы в будущем, все, что вам нужно сделать, это найти элементы с именем <escaped>, что является простой и естественной задачей для любого XML-инструмента.

Я не знаю, находится ли дизайн этих файлов XML под вашим контролем или нет. Если нет, у вас, по крайней мере, должна быть возможность отправить отзыв дизайнеру. Если дизайнер, не очень хорошо разбирающийся в XML-вещах, допускает ошибку проектирования, в его интересах узнать об этом, чтобы иметь возможность исправить ее или, по крайней мере, избежать той же ошибки в будущих проектах. Если вы работаете по цепочке подчинения, а разработчик XML находится в другом отделе, правильный путь для обратной связи может быть через вашего руководителя. В интересах отдела знать, производят ли они непереносимые проекты XML.

person LarsH    schedule 09.10.2012
comment
В каждом XML-документе, который я создал, cdata не использует тот же узел, что и любые другие узлы. Должен любить работать с тем, что создал кто-то другой. К сожалению, программное обеспечение, которое создало исходный экспорт данных (спецификация openXML), который я анализирую, принадлежит хорошо зарекомендовавшей себя организации, которая, как я выяснил, путается в способе экспорта данных, чтобы получить дополнительный доход от консалтинга. - person Reahreic; 13.10.2012
comment
Спасибо за ваше руководство. Поскольку я все еще изучаю определенные методы программирования, его сообщения, подобные вашим, гарантируют, что я не изучу плохие методы. Я только надеюсь, что когда я стану лучше, я смогу отдать должное сообществу, направляя других, как вы. - person Reahreic; 13.10.2012
comment
@Reahreic: спасибо за ваши комментарии. Можете ли вы дать мне указатель на соответствующую спецификацию OpenXML? Я хотел бы убедиться, что разделы CDATA действительно важны, а не поможет ли простой поиск текстовых узлов. - person LarsH; 14.10.2012
comment
я не могу сказать вам, в какую спецификацию Open XML они экспортируют только то, что они ссылаются на возможность импортировать и экспортировать данные в ваши приложения и из них, используя open xml. - person Reahreic; 14.10.2012