2016-06-24 2 views
0

minidom 모듈을 사용하여 데이터에서 XML 문서를 만듭니다. 내가 거기에 넣어 내 문자열을 탈출 minidom을 방지하기 위해 몇 가지 파이썬 방법을 찾기 위해 사투를 벌인거야 순간 Python xml.dom.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하고 패치 내 :
      • _write_data


    나는 두 가지 기능을 monkeypathing하여이를 방지 할 수있는 방법을 발견이 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=' ')) 
    

    : 1,363,210

    나는 몇 가지 예제를 준비했습니다 , 실수를하지 않도록주의해야합니다.

    나에게 당신이 가지고 올 수있는 문제에 대한 가장 파이썬 솔루션을 제시해주십시오 - 그래서 마침내 Snowmans ;-)

    & # x2603을 즐길 수 있습니다; & #의 xfe0e;

    가이 노드의 새로운 유형을 정의 할 수 없습니다 :

  • 답변

    0

    여기 내 문제에 대해 더 생각, 내가 한 생각을했다?

    실제로! 그 후

    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에 대한 몇 가지 도우미 함수를 작성 :

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

    그래서, 나는 거기에 내 자신의 노드가 정의합니다. 아무 일도없는 것처럼

    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> 
    
    관련 문제