【问题标题】:preserve entity references when parsing xml解析 xml 时保留实体引用
【发布时间】:2013-07-26 21:00:08
【问题描述】:

运行以下简单脚本:

from lxml import etree

tree = etree.parse('VimKeys.xml')
root = tree.getroot()

for child in root:
  print ("<table>")
  print ("<caption>" + child.attrib['title'] + "</caption>")
  for child in child:
    print ("<tr>")
    print ("<th>" + child.text + "</th>")
    print ("<td>" + child.attrib['description'] + "</td>")
    print ("</tr>")
  print ("</table>")

针对以下 xml:

<keycommands>
  <category title="Editing">
    <key description="replace">r</key>
    <key description="change, line">c,cc</key>
    <key description="join line with the following">J</key>
    <key description="delete &amp; insert">s</key>
    <key description="change case">~</key>
    <key description="apply last edit">.</key>
    <key description="undo, redo">u,⌃+r</key>
    <key description="indent line right, left">&gt;&gt;,&lt;&lt;</key>
    <key description="auto-indent line">==</key>
  </category>
</keycommands>

结果如下:

<caption>Editing</caption>
  <tr>
    <th>r</th>
    <td>replace</td>
  </tr>
  <tr>
    <th>c,cc</th>
    <td>change, line</td>
  </tr>
  <tr>
    <th>J</th>
    <td>join line with the following</td>
  </tr>
  <tr>
    <th>s</th>
    <td>delete & insert</td>
  </tr>
  <tr>
    <th>~</th>
    <td>change case</td>
  </tr>
  <tr>
    <th>.</th>
    <td>apply last edit</td>
  </tr>
  <tr>
    <th>u,⌃+r</th>
    <td>undo, redo</td>
  </tr>
  <tr>
    <th>>>,<<</th>
    <td>indent line right, left</td>
  </tr>
  <tr>
    <th>==</th>
    <td>auto-indent line</td>
  </tr>
</table>

这是无效的 HTML,因为小于和大于号被引用为

&lt; and &gt;

在源文档中。

如何在最终产品中保留这些内容?

【问题讨论】:

    标签: python xml parsing elementtree


    【解决方案1】:

    使用the Element class 构建一个新的XML 树,而不是使用print 来“手动”格式化它:

    import lxml.etree as ET
    
    tree = ET.parse('VimKeys.xml')
    root = tree.getroot()
    
    newroot = ET.Element('root')
    for i, child in enumerate(root):
        table = ET.Element('table')
        newroot.insert(i, table)
        caption = ET.Element('caption')
        caption.text = child.attrib['title']
        table.insert(0, caption)
        for j, c in enumerate(child, 1):
            tr = ET.Element('tr')
            table.insert(j, tr)
            th = ET.Element('th')
            th.text = c.text
            tr.insert(0, th)
    
            td = ET.Element('td')
            td.text = c.attrib['description']
            tr.insert(1, td)
    
    print(ET.tostring(newroot, pretty_print=True))
    

    或者,使用the E-factory。这样做会使预期的结构更易于阅读(和修改):

    import lxml.etree as ET
    import lxml.builder as builder
    
    tree = ET.parse('VimKeys.xml')
    root = tree.getroot()
    
    E = builder.E
    tables = []
    for child in root:
        trs = []
        for c in child:
            trs.append(E('tr',
                         E('th', c.text),
                         E('td', c.attrib['description'])))
        tables.append(E('table',
                        E('caption', child.attrib['title']),
                        *trs))
    
    newroot = E('root', *tables)
    print(ET.tostring(newroot, pretty_print=True))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 2019-07-07
      • 2011-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多