【问题标题】:How to use lxml and python to pretty print a subtree of an xml file?如何使用 lxml 和 python 漂亮地打印 xml 文件的子树?
【发布时间】:2019-03-27 19:54:19
【问题描述】:

我有以下代码使用 pythonlxml 来漂亮地打印文件 example.xml

python -c '
from lxml import etree;
from sys import stdout, stdin;

parser=etree.XMLParser(remove_blank_text=True, strip_cdata=False);
tree=etree.parse(stdin, parser)
tree.write(stdout, pretty_print = True)' < example.xml

我使用 lxml 是因为保留原始文件的保真度很重要,包括保留 CDATA 惯用语。这是我正在使用的文件 example.xml

<projects><project name="helloworld" threads="1" pubsub="auto" heartbeat-interval="1">
<description><![CDATA[This is a sample project]]></description>  <metadata>    <meta id="studioUploadedBy">anonymous</meta>
<meta id="studioUploaded">1550863090439</meta>    <meta id="studioModifiedBy">anonymous</meta>
<meta id="studioModified">1550863175384</meta>    <meta id="studioTags">helloworld</meta>
<meta id="studioVersionNotes">This is just a sample project</meta>    <meta id="layout">{"cq1":{"Source1":{"x":50,"y":-290}}}</meta>
</metadata>  <contqueries>    <contquery name="cq1">      <windows>        <window-source pubsub="true" name="Source1">
<schema>            <fields>              <field name="name" type="string" key="true"/>            </fields>
</schema>        </window-source>      </windows>    </contquery>  </contqueries> </project></projects>

它生成以下输出:

<projects>
  <project name="helloworld" threads="1" pubsub="auto" heartbeat-interval="1">
    <description><![CDATA[This is a sample project]]></description>
    <metadata>
      <meta id="studioUploadedBy">anonymous</meta>
      <meta id="studioUploaded">1550863090439</meta>
      <meta id="studioModifiedBy">anonymous</meta>
      <meta id="studioModified">1550863175384</meta>
      <meta id="studioTags">helloworld</meta>
      <meta id="studioVersionNotes">This is just a sample project</meta>
      <meta id="layout">{"cq1":{"Source1":{"x":50,"y":-290}}}</meta>
    </metadata>
    <contqueries>
      <contquery name="cq1">
        <windows>
          <window-source pubsub="true" name="Source1">
            <schema>
              <fields>
                <field name="name" type="string" key="true"/>
              </fields>
            </schema>
          </window-source>
        </windows>
      </contquery>
    </contqueries>
  </project>
</projects>

这几乎是我想要的,只是我想获得一个子树。我希望能够只获得子树&lt;project name="helloworld"...&gt;&lt;/project&gt;。我将如何根据 lxml 修改上述 Python 代码来做到这一点?

【问题讨论】:

    标签: python lxml


    【解决方案1】:

    我们可以使用xpath 捕获嵌套元素。元素对象不提供相同的.write() 功能,因此我们需要不同的输出机制。

    怎么样...

    python -c '
    from lxml import etree;
    from sys import stdout, stdin;
    
    parser=etree.XMLParser(remove_blank_text=True, strip_cdata=False);
    tree=etree.parse(stdin, parser)
    # assuming there will be exactly 1 project
    project=tree.xpath("project")[0]
    print etree.tostring(project, pretty_print = True)' < example.xml
    

    【讨论】:

    • 我不确定这是否像我想要的那样灵活,但我真的很感谢你的想法!
    • 尽可能灵活。此外,对于非 ASCII 输入,您可能希望将 encoding='unicode' 传递给 tostring()
    【解决方案2】:

    您可以使用 tree.find 来获取您需要提取的 xml 元素。他们将其转换为元素树。在这种情况下,您可以在生成的 elementtree (et) 上发出 write 语句。

    python -c '
               from lxml import etree;
               from sys import stdout, stdin;
               parser=etree.XMLParser(remove_blank_text=True,strip_cdata=False);
               tree=etree.parse(stdin, parser)
               e = tree.find("project")
               et = etree.ElementTree(e)                                                                                                                                                                             
               et.write(stdout, pretty_print = True)'
    

    【讨论】:

    • 我已编辑您的代码以添加检查,因为如果项目是 xml 文档的根元素,它将失败
    • 对于 Python 3,使用 stdout.buffer 代替 stdout
    猜你喜欢
    • 2018-05-27
    • 1970-01-01
    • 2011-07-02
    • 2018-10-04
    • 2015-05-03
    • 2017-12-19
    相关资源
    最近更新 更多