2009-07-27 9 views
3

Je suis intrigué par la manipulation de l'élément vide par l'analyseur minidom, comme indiqué dans la section de code suivante.Gestion des éléments XML vides en Python

import xml.dom.minidom 

doc = xml.dom.minidom.parseString('<value></value>') 
print doc.firstChild.nodeValue.__repr__() 
# Out: None 
print doc.firstChild.toxml() 
# Out: <value/> 

doc = xml.dom.minidom.Document() 
v = doc.appendChild(doc.createElement('value')) 
v.appendChild(doc.createTextNode('')) 
print v.firstChild.nodeValue.__repr__() 
# Out: '' 
print doc.firstChild.toxml() 
# Out: <value></value> 

Comment puis-je obtenir un comportement cohérent? Je voudrais recevoir chaîne vide comme valeur de élément vide (IS est ce que j'ai mis dans la structure XML en premier lieu).

Répondre

4

Cracking xml.dom.minidom ouverte et la recherche de « /> », nous trouvons ceci:

# Method of the Element(Node) class. 
def writexml(self, writer, indent="", addindent="", newl=""): 
    # [snip] 
    if self.childNodes: 
     writer.write(">%s"%(newl)) 
     for node in self.childNodes: 
      node.writexml(writer,indent+addindent,addindent,newl) 
     writer.write("%s</%s>%s" % (indent,self.tagName,newl)) 
    else: 
     writer.write("/>%s"%(newl)) 

On peut en déduire que la forme courte balise de fin se produit uniquement lorsque childNodes est un vide liste. En effet, cela semble être vrai:

>>> doc = Document() 
>>> v = doc.appendChild(doc.createElement('v')) 
>>> v.toxml() 
'<v/>' 
>>> v.childNodes 
[] 
>>> v.appendChild(doc.createTextNode('')) 
<DOM Text node "''"> 
>>> v.childNodes 
[<DOM Text node "''">] 
>>> v.toxml() 
'<v></v>' 

Comme l'a souligné Lloyd, la spécification XML ne fait aucune distinction entre les deux. Si votre code fait faire la distinction, cela signifie que vous devez repenser comment vous voulez sérialiser vos données. Xml.dom.minidom affiche simplement quelque chose différemment car il est plus facile de coder. Vous pouvez cependant obtenir une sortie cohérente. Il suffit d'hériter de la classe Element et de remplacer la méthode toxml pour qu'elle imprime le formulaire de balise de fin de ligne lorsqu'il n'y a aucun nœud enfant avec du contenu textuel non vide. Puis monkeypatch le module pour utiliser votre nouvelle classe Element.

+0

C'est exactement ce que je veux dire. XML spec définit deux formes comme équivalentes, mais minidom traite comme '' si créé au moment de l'exécution, et analyse cependant en élément "v" sans noeud enfant TextElemet. – Josip

+0

J'ai suivi votre conseil pour changer mon approche sur la sérialisation des données. Je vais essayer JSON, car il correspond mieux à mes besoins. Merci pour l'aide. – Josip

1
value = thing.firstChild.nodeValue or '' 
+0

Malheureusement, cela ne résout pas mon problème. Dans mon code, j'appelle la méthode replaceWholeText sur TextElement dans le document XML. Si je stockais précédemment une chaîne vide dans ce TextElement, il disparaîtrait la prochaine fois que le fichier XML serait analysé, et je serais incapable d'appeler la méthode replaceWholeText. Je pourrais reconstruire cet élément si ce n'est pas là, mais ce serait un hack très moche. – Josip

+0

Que voulez-vous dire "reconstruire l'élément"? Il existe, sa valeur est simplement nulle au lieu de ''. –

1

La spécification Xml ne distingue pas ces deux cas.

Questions connexes