2016-06-24 5 views
0

Ich verwende das minidom Modul, um XML-Dokumente aus meinen Daten zu erstellen.Python xml.dom.minidom - Bitte nicht entkommen meine Strings

Im Moment bin ich kämpfen einige pythonic Weg zu finden minidom entweicht meinen Strings ich da ..

Ursache allen Übels ist das (auf im Modul 302 Linie) _write_data Verfahren setzen zu verhindern:

def _write_data(writer, data): 
    "Writes datachars to writer." 
    if data: 
     data = data.replace("&", "&amp;").replace("<", "&lt;"). \ 
        replace("\"", "&quot;").replace(">", "&gt;") 
     writer.write(data) 

Alles, was ich will, ist die data ohne diese replace gen.


fand ich einige Möglichkeit, dies durch monkeypathing zwei Funktionen zu verhindern:

  • writexml des Elternknotens
  • und innerhalb dieses Patch:
    • _write_data

Ich habe einige Beispiele vorbereitet:

<?xml version="1.0" ?> 
<root> 
<evil>&amp;#x2603;&amp;#xfe0e;</evil> 
<good>&#x2603;&#xfe0e;</good> 
</root> 

<?xml version="1.0" ?> 
<root> 
<evil>&amp;#x2603;&amp;#xfe0e;</evil> 
<good>&amp;#x2603;&amp;#xfe0e;</good> 
</root> 

Ich persönlich glaube nicht, dass dies eine gute Code, wie es mit den Interna von verunstaltet um minidom:

from xml.dom import minidom 

SNOWMAN = '&#x2603;&#xfe0e;' 

imp = minidom.getDOMImplementation() 
dom = imp.createDocument(None, 'root', None) 
root = dom.documentElement 

evil = dom.createElement('evil') 
root.appendChild(evil) 
# this does unwanted double escaping: 
evil.appendChild(dom.createTextNode(SNOWMAN)) 

# now for something completely different ... 
# this is some way to fix this: 
good = dom.createElement('good') 
root.appendChild(good) 

# - store original ``writexml`` and ``_write_data`` 
original_writexml = good.writexml 
original_write_data = minidom._write_data 


def fake_writexml(writer, indent, addindent, newl): 
    def fake_writedata(writer, data): 
     if data: 
      writer.write(data) 

    # - overwrite ``_write_data`` 
    minidom._write_data = fake_writedata 

    # - call original ``writexml`` 
    # -> which itself calls the now patched ``_write_data`` 
    original_writexml(writer, indent, addindent, newl) 

    # - reset ``_write_data`` again 
    minidom._write_data = original_write_data 

# - overwrite ``writexml`` 
good.writexml = fake_writexml 

# - do stuff 
good.appendChild(dom.createTextNode(SNOWMAN)) 

# -> yay, it works! 
print(dom.toprettyxml(indent=' ')) 

# - reset ``writexml`` again 
good.writexml = original_writexml 
# -> returns trash again.. 
print(dom.toprettyxml(indent=' ')) 

Es diese Ausgabe erzeugen wird und du musst aufpassen, dass du keine Fehler machst.

Bitte zeigen Sie mir die pythonic Lösung für dieses Problem, das Sie mit oben kommen können - so kann ich endlich das

& # x2603 ;-) Snowmans genießen; & # xfe0e;

Antwort

0

denkt weiter über mein Problem hier, ich hatte eine Idee:

Ist es nicht möglich, eine neue Art von Knoten zu definieren?

In der Tat - es ist!

from xml.dom import minidom 

SNOWMAN = '&#x2603;&#xfe0e;' 

imp = minidom.getDOMImplementation() 
dom = imp.createDocument(None, 'root', None) 

So definiere ich meine eigenen Knoten gibt:

class RawText(minidom.Text): 
    def writexml(self, writer, indent='', addindent='', newl=''): 
     ''' 
     patching minidom.Text.writexml:1087 
     the original calls minidom._write_data:302 
     below is a combined version of both, but without the '&' replacements and so on.. 
     ''' 
     if self.data: 
      writer.write('{}{}{}'.format(indent, self.data, newl)) 

Danach habe ich einige Helferfunktion für die ursprüngliche minidom.Document schreiben neue Knoten meiner eigenen Art zu erstellen.

def createRawTextNode(data): 
    ''' 
    helper function for minidom.Document:1519 to create Nodes of RawText 
    see minidom.Document.createTextNode:1656 
    ''' 
    if not isinstance(data, str): 
     raise TypeError('node contents must be a string') 
    r = RawText() 
    r.data = data 
    r.ownerDocument = dom # there is no self 
    return r 

# ... and attach the helper function 
dom.createRawTextNode = createRawTextNode 

Und dann weiter, als ob nichts geschehen:

root = dom.documentElement 

evil = dom.createElement('evil') 
root.appendChild(evil) 
evil.appendChild(dom.createTextNode(SNOWMAN)) 

good = dom.createElement('good') 
root.appendChild(good) 
# use helper function to create Nodes of RawText 
good.appendChild(dom.createRawTextNode(SNOWMAN)) 

# yay, works! |o_0| 
print(dom.toprettyxml(indent=' ')) 

Schließlich tut es das, was ich will!

Beide entkamen und entkrypten Strings in meiner Ausgabe ohne Probleme.

<?xml version="1.0" ?> 
<root> 
<evil>&amp;#x2603;&amp;#xfe0e;</evil> 
<good>&#x2603;&#xfe0e;</good> 
</root> 
Verwandte Themen