Как использовать lxml и python для печати поддерева XML-файла? - PullRequest
4 голосов
/ 27 марта 2019

У меня есть следующий код, использующий python с lxml , чтобы красиво напечатать файл 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

I 'Я использую 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>

Это почти то, что я хочукроме того, что я хотел бы получить поддерево.Я хотел бы получить только поддерево <project name="helloworld"...> через </project>.Как бы я изменил приведенный выше код Python на основе lxml , чтобы сделать это?

Ответы [ 2 ]

3 голосов
/ 27 марта 2019

Мы можем захватить вложенный элемент, используя 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
2 голосов
/ 27 марта 2019

Вы можете использовать tree.find, чтобы получить необходимый элемент xml.Их конвертируют в дерево элементов.Затем в этом случае вы можете выполнить оператор write для результирующего дерева элементов (et).

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