2016-06-24 19 views
0

minidomモジュールを使用して、自分のデータからXML文書を作成しています。Python xml.dom.minidom - 文字列をエスケープしないでください

私はそこに入れて、私の文字列をエスケープからminidomを防ぐためにいくつかの神託の方法を見つけるのに苦労しています現時点では..すべての悪の

原因は、(モジュール内のライン302上の)_write_dataメソッドです。

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

私が欲しいのは、これらのreplaceメントなしdataです。親ノード

  • とそのパッチ内の

    • writexml


      私は2つの機能をmonkeypathingことにより、これを防ぐためにいくつかの方法を見つけた

      • _write_data
    それはminidomの内部と周り台無しとして個人的に

    <?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> 
    

    は、私は、これは良いコードであるとは思わない:それは、この出力を生成します

    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=' ')) 
    

    私はいくつかの例を用意しましたあなたは間違いをしないように気をつけなければなりません。

    私にあなたが思い付くことができ、その問題に最も神託のソリューションをご提示ください - ので、私は最終的にSnowmans ;-)

    &#x2603を楽しむことができます;&#のxfe0e。

    は、ノードの新しいタイプを定義することはできません:

  • 答えて

    0

    ここに私の問題について、さらに考えると、私は1つのアイデアを持っていましたか?

    実際、そうです!だから、

    from xml.dom import minidom 
    
    SNOWMAN = '&#x2603;&#xfe0e;' 
    
    imp = minidom.getDOMImplementation() 
    dom = imp.createDocument(None, 'root', None) 
    

    、私はそこに自分のノードを定義します。その後

    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)) 
    

    私は自分のタイプの新しいノードを作成するには、元のminidom.Documentのためのいくつかのヘルパー関数を記述します。何事もなかったかのよう

    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 
    

    そして、継続:

    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=' ')) 
    

    を最後に、私が欲しいものを行います!

    出力にエスケープされた文字列とエスケープされていない文字列の両方が問題なく出力されます。

    <?xml version="1.0" ?> 
    <root> 
    <evil>&amp;#x2603;&amp;#xfe0e;</evil> 
    <good>&#x2603;&#xfe0e;</good> 
    </root> 
    
    関連する問題