2009-02-27 17 views
12

Sono in grado di ottenere il valore nel tag immagine (vedere XML sotto), ma non il tag Category. La differenza è che una è una sezione CDATA e l'altra è solo una stringa. Qualsiasi aiuto sarebbe apprezzato.xml.dom.minidom: acquisizione dei valori 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]) 

risposta

23

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

minidom non appiattire via <! [CDATA [sezioni di testo normale, li lascia come nodi DOM CDATASection . (Probabilmente dovrebbe, almeno opzionalmente. DOM Level 3 LS usa il valore predefinito per livellarlo, per quello che vale, ma il minidom è molto più vecchio di DOM L3.)

Quindi il primo figlio di categoria è un nodo di testo che rappresenta lo spazio bianco tra il tag aperto Categoria> < e l'inizio della sezione CDATA. Ha due fratelli: il nodo CDATASection e un altro nodo testo finale.

Quello che probabilmente vuoi sono i dati testuali di tutti i bambini di Categoria. In DOM Level 3 Core chiami semplicemente:

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

ma minidom non lo supporta ancora. Le versioni più recenti, tuttavia, sostenere un altro metodo di livello 3 è possibile utilizzare per fare la stessa cosa in un modo più indiretto:

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

Qual è lo zero per? –

+0

'getElementsByTagName' restituisce un' NodeList', '[0]' ottiene il primo elemento nell'elenco. Il Python DOM Bind richiede che '[n]' sia una scorciatoia per DOM '.item (n)'. – bobince

7

CDATA è proprio nodo, quindi gli elementi Categoria qui in realtà hanno tre figli, uno spazio bianco nodo di testo, il nodo CDATA e un altro nodo di spazi bianchi. Stai solo guardando quello sbagliato, tutto qui. Non vedo alcun modo più evidente per interrogare per il nodo CDATA, ma si può tirare fuori in questo modo:

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

ho incontrato un problema simile. La mia soluzione era simile a quello che ironfroggy risposto, ma implementato in un modo più generale:

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

tipo di nodo di CDATA è 4 (CDATA_SECTION_NODE)

+1

Hai salvato il mio progetto, straniero! –