Подтвердить что ты не робот

Xml.dom.minidom: получение значений CDATA

Я могу получить значение в теге изображения (см. XML ниже), но не тег Category. Разница в том, что это раздел CDATA, а другой - просто строка. Любая помощь будет оценена.

from xml.dom import minidom

xml = """<?xml version="1.0" ?>
<ProductData>
    <ITEM Id="0471195">
        <Category>
            <![CDATA[Homogenizers]]>        
        </Category>
        <Image>
            0471195.jpg
        </Image>
    </ITEM>
    <ITEM Id="0471195">
        <Category>
            <![CDATA[Homogenizers]]>        
        </Category>
        <Image>
            0471196.jpg
        </Image>
    </ITEM>
</ProductData>
"""

bad_xml_item_count = 0
data = {}
xml_data = minidom.parseString(xml).getElementsByTagName('ProductData')
parts = xml_data[0].getElementsByTagName('ITEM')
for p in parts:
    try:
        part_id = p.attributes['Id'].value.strip()
    except(KeyError):
        bad_xml_item_count += 1
        continue
    if not part_id:
        bad_xml_item_count += 1
        continue
    part_image = p.getElementsByTagName('Image')[0].firstChild.nodeValue.strip()
    part_category = p.getElementsByTagName('Category')[0].firstChild.data.strip()
    print '\t'.join([part_id, part_category, part_image])
4b9b3361

Ответ 1

p.getElementsByTagName( 'Категория') [0].firstChild

minidom не сглаживается <! [CDATA [разделы до простого текста, он оставляет их в качестве узлов DOM CDATASection. (По-видимому, это должно быть, по крайней мере, необязательно. DOM Level 3 LS по умолчанию сглаживает их, за что стоит, но minidom намного старше DOM L3.)

Таким образом, firstChild of Category представляет собой текст node, представляющий пробел между тегом <Category> open и началом раздела CDATA. Он имеет двух братьев и сестер: CDATASection node и еще один пробельный пробел Text node.

Возможно, вам нужны текстовые данные всех детей категории. В DOM Level 3 Core вы просто вызываете:

p.getElementsByTagName('Category')[0].textContent

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

p.getElementsByTagName('Category')[0].firstChild.wholeText

Ответ 2

CDATA - это собственный node, поэтому элементы категории на самом деле имеют трех детей, пробельный текст node, CDATA node и еще один пробел node. Ты просто смотришь на не того, и все. Я не вижу более очевидного способа запроса для CDATA node, но вы можете вытащить его так:

[n for n in category.childNodes if n.nodeType==category.CDATA_SECTION_NODE][0]

Ответ 3

У меня возникла аналогичная проблема. Мое решение было похоже на то, что ответил ironfroggy, но реализовано более общим образом:

for node in parentNode.childNodes:
        if node.nodeType == 4:
            cdataContent = node.data.strip()

Тип CDATA node равен 4 (CDATA_SECTION_NODE)