2015-11-06 14 views
8

Tôi muốn giữ lại các nhận xét một cách trung thực nhất có thể trong khi thao tác XML.Bảo vệ trung thành các nhận xét trong XML được phân tích cú pháp (Python 2.7)

Tôi đã quản lý để lưu giữ các nhận xét, nhưng nội dung đang bị thoát XML.

#!/usr/bin/env python 
# add_host_to_tomcat.py 

import xml.etree.ElementTree as ET 
from CommentedTreeBuilder import CommentedTreeBuilder 
parser = CommentedTreeBuilder() 

if __name__ == '__main__': 
    filename = "/opt/lucee/tomcat/conf/server.xml" 

    # this is the important part: use the comment-preserving parser 
    tree = ET.parse(filename, parser) 

    # get the node to add a child to 
    engine_node = tree.find("./Service/Engine") 

    # add a node: Engine.Host 
    host_node = ET.SubElement(
     engine_node, 
     "Host", 
     name="local.mysite.com", 
     appBase="webapps" 
    ) 
    # add a child to new node: Engine.Host.Context 
    ET.SubElement(
     host_node, 
     'Context', 
     path="", 
     docBase="/path/to/doc/base" 
    ) 

    tree.write('out.xml') 
#!/usr/bin/env python 
# CommentedTreeBuilder.py 

from xml.etree import ElementTree 

class CommentedTreeBuilder (ElementTree.XMLTreeBuilder): 
    def __init__ (self, html = 0, target = None): 
     ElementTree.XMLTreeBuilder.__init__(self, html, target) 
     self._parser.CommentHandler = self.handle_comment 

    def handle_comment (self, data): 
     self._target.start(ElementTree.Comment, {}) 
     self._target.data(data) 
     self._target.end(ElementTree.Comment) 

Tuy nhiên, ý kiến ​​như như:

<!-- 
EXAMPLE HOST ENTRY: 
    <Host name="lucee.org" appBase="webapps"> 
     <Context path="" docBase="/var/sites/getrailo.org" /> 
    <Alias>www.lucee.org</Alias> 
    <Alias>my.lucee.org</Alias> 
    </Host> 

HOST ENTRY TEMPLATE: 
    <Host name="[ENTER DOMAIN NAME]" appBase="webapps"> 
     <Context path="" docBase="[ENTER SYSTEM PATH]" /> 
    <Alias>[ENTER DOMAIN ALIAS]</Alias> 
    </Host> 
    --> 

End lên như:

<!-- 
      EXAMPLE HOST ENTRY: 
    &lt;Host name="lucee.org" appBase="webapps"&gt; 
     &lt;Context path="" docBase="/var/sites/getrailo.org" /&gt; 
     &lt;Alias&gt;www.lucee.org&lt;/Alias&gt; 
     &lt;Alias&gt;my.lucee.org&lt;/Alias&gt; 
    &lt;/Host&gt; 

    HOST ENTRY TEMPLATE: 
    &lt;Host name="[ENTER DOMAIN NAME]" appBase="webapps"&gt; 
     &lt;Context path="" docBase="[ENTER SYSTEM PATH]" /&gt; 
     &lt;Alias&gt;[ENTER DOMAIN ALIAS]&lt;/Alias&gt; 
    &lt;/Host&gt; 
    --> 

Tôi cũng đã cố gắng self._target.data(saxutils.unescape(data)) trong CommentedTreeBuilder.py, nhưng nó dường như không làm gì cả . Trong thực tế, tôi nghĩ rằng vấn đề xảy ra ở đâu đó sau khi bước handle_commment().

Nhân tiện, câu hỏi này tương tự như this.

Trả lời

8

Được thử nghiệm với Python 2.7 và 3.5, mã sau sẽ hoạt động như dự định.

#!/usr/bin/env python 
# CommentedTreeBuilder.py 
from xml.etree import ElementTree 

class CommentedTreeBuilder(ElementTree.TreeBuilder): 
    def __init__(self, *args, **kwargs): 
     super(CommentedTreeBuilder, self).__init__(*args, **kwargs) 

    def comment(self, data): 
     self.start(ElementTree.Comment, {}) 
     self.data(data) 
     self.end(ElementTree.Comment) 

Sau đó, trong việc sử dụng mã chính

parser = ET.XMLParser(target=CommentedTreeBuilder()) 

như phân tích cú pháp thay vì hiện tại.

Nhân tiện, các nhận xét hoạt động chính xác ra khỏi hộp với lxml. Tức là, bạn chỉ có thể làm

import lxml.etree as ET 
tree = ET.parse(filename) 

mà không cần bất kỳ điều nào ở trên.

+0

Cả hai giải pháp này dường như giữ lại các nhận xét, cảm ơn! Nhưng các yếu tố khác được định dạng lại (và các thuộc tính sắp xếp lại, có khả năng). Tôi biết nó không quan trọng đối với khả năng đọc máy, nhưng vì mục đích của tôi (khả năng đọc của con người, kiểm soát phiên bản và chỉ chạm vào các yếu tố được chạm vào rõ ràng), điều đó quan trọng. FWIW, phiên bản gốc của tôi xảy ra để lại các yếu tố khác nguyên vẹn (tức là đã được định dạng là bản gốc). Câu trả lời này giải quyết câu hỏi rõ ràng của tôi, vì vậy nó sẽ nhận được giải thưởng câu trả lời, nhưng tôi muốn biết nếu không có chú thích định dạng phần tử bảo quản cũng có thể. –

+0

Theo như tôi thấy, những thứ duy nhất được sửa đổi là thứ tự các thuộc tính và khoảng trắng bên trong các thẻ (đúng với tôi nếu tôi thiếu bất kỳ thứ gì). Bạn thường không nên có hoặc quan tâm đến điều sau. Vì các thuộc tính được lưu trữ trong một từ điển trong 'xml', thứ tự của chúng là ngẫu nhiên trong đầu ra. Để khắc phục điều đó, bạn có thể sử dụng giải pháp tương tự như giải pháp nhận xét, xem http://stackoverflow.com/q/2741480/2997179. Hoặc như thử nghiệm nhanh với 'lxml' cho thấy, nó dường như để bảo vệ trật tự thuộc tính và có vẻ như một giải pháp khả thi. Dù bằng cách nào, tôi nghĩ rằng điều này xứng đáng là một câu hỏi SO riêng biệt. –

+0

Được rồi .. ở đầu thuộc tính, 'xml' cũng loại bỏ các thẻ lệnh xử lý (ví dụ:' ') Và đổi tên các không gian tên xmlns. Một lần nữa, 'lxml' không làm gì cả. –

Các vấn đề liên quan