2009-02-27 20 views
12

Jestem w stanie uzyskać wartość w tagu obrazu (patrz XML poniżej), ale nie tag kategorii. Różnica polega na tym, że jedna to sekcja CDATA, a druga to tylko ciąg. Każda pomoc będzie doceniona.xml.dom.minidom: Uzyskiwanie wartości 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]) 

Odpowiedz

23

p.getElementsByTagName ('Kategoria') [0] .firstChild

minidom nie spłaszczyć dala <! [CDATA [sekcje do zwykłego tekstu, pozostawia je jako węzły DOM CDATASection . (Prawdopodobnie powinien, przynajmniej opcjonalnie, DOM Level 3 LS domyślnie spłaszczać je, bo to jest warte, ale minidom jest dużo starszy niż DOM L3.)

Tak więc firstChild of Category jest węzłem Text reprezentującym białe spacje < Kategoria> otwórz tag i początek sekcji CDATA. Ma on dwoje rodzeństwa: węzeł CDATASection i kolejny końcowy węzeł Tekst.

To, czego prawdopodobnie chcesz, to dane tekstowe wszystkich dzieci w Kategorii. W DOM Level 3 Core wystarczy zadzwonić:

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

, ale minidom tego jeszcze nie obsługuje. Najnowsze wersje mają jednak wspierać inną metodę Poziom 3 można użyć, aby zrobić to samo w bardziej okrężną drogą:

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

Co jest zero? –

+0

'getElementsByTagName' zwraca' NodeList', '[0]' dostaje pierwszy element na liście. Powiązanie DOM Python wymaga, aby '[n]' był skrótem dla DOM '.item (n)'. – bobince

7

CDATA ma własny węzeł, więc elementy Kategoria tu rzeczywiście mają troje dzieci, a odstępy węzeł tekstowy, węzeł CDATA i inny węzeł białych znaków. Po prostu patrzysz na niewłaściwą, to wszystko. Nie widzę żadnej bardziej oczywisty sposób do kwerendy dla węzła CDATA, ale można go wyciągnąć tak:

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

ja wpadłem na podobny problem. Moje rozwiązanie było podobne do tego, co ironfroggy odpowiedział, ale realizowane w bardziej ogólny sposób:

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

CDATA typ węzła 4 (CDATA_SECTION_NODE)

+1

Zapisałeś mój projekt, nieznajomy! –