xml.dom.minidom:获取CDATA值

时间:2009-02-27 23:20:56

标签: python xml

我能够获取图像标记中的值(请参阅下面的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])

3 个答案:

答案 0 :(得分:24)

  

p.getElementsByTagName( '分类')[0] .firstChild

minidom并没有变平&lt;![CDATA [部分为纯文本,它将它们留作DOM CDATASection节点。 (可以说,它应该至少是可选的.DOM Level 3 LS默认为扁平化它们的价值,但minidom比DOM L3更老。)

因此,类别的firstChild是一个Text节点,表示&lt; Category&gt;之间的空格。打开标签和CDATA部分的开头。它有两个兄弟:CDATASection节点和另一个尾随空格Text节点。

你可能想要的是所有类别孩子的文本数据。在DOM Level 3 Core中你只需要调用:

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

但是minidom还不支持。但是,最新版本支持另一种Level 3方法,您可以使用它以更迂回的方式执行相同的操作:

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

答案 1 :(得分:7)

CDATA是它自己的节点,因此这里的Category元素实际上有三个子节点,一个空白文本节点,CDATA节点和另一个空白节点。你只是看错了,就是这样。我没有看到任何更明显的方法来查询CDATA节点,但你可以这样解决它:

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

答案 2 :(得分:3)

我遇到了类似的问题。我的解决方案类似于ironfroggy的回答,但是以更一般的方式实施:

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

CDATA的节点类型为4(CDATA_SECTION_NODE