使用 xml.etree.ElementTree 捕获所有 XML 元素路径

gri*_*ron 5 python xml elementtree

使用 python import lxml 我可以递归地打印每个元素的路径列表:

from lxml import etree
root = etree.parse(xml_file)
for e in root.iter():
    path = root.getelementpath(e)
    print(path)
Run Code Online (Sandbox Code Playgroud)

结果:

TreatmentEpisodes
TreatmentEpisodes/TreatmentEpisode
TreatmentEpisodes/TreatmentEpisode/SourceRecordIdentifier
TreatmentEpisodes/TreatmentEpisode/FederalTaxIdentifier
TreatmentEpisodes/TreatmentEpisode/ClientSourceRecordIdentifier
etc.
Run Code Online (Sandbox Code Playgroud)

注意:我正在使用此 XSD: https://www.myflfamilies.com/service-programs/samh/155-2/155-2-v14/schemas/TreatmentEpisodeDataset.xsd

我想使用 import xml.etree.ElementTree as ET 做同样的事情 ...但是 ElementTree 似乎没有与 lxml getelementpath() 等效的函数。

我已阅读文档。我已经用谷歌搜索了好几天了。我尝试过 XPath。我猜测使用 iter() 并尝试了“getpath()”、“Element.getpath()”等,希望发现一个未记录的功能。失败。

也许我遇到了“用户错误”的极端情况,如果这是重复的,请原谅我。

我想我在这里找到了答案:使用 ElementTree getpath() 动态获取 Xpath但 XPathEvaluator 似乎只在“已知”元素上运行 - 它没有“给我一切”的选项。

这是我尝试过的:

import xml.etree.ElementTree as ET
tree = etree.parse(xml_file)
for entry in tree.xpath('//TreatmentEpisode'):
    print(entry)
Run Code Online (Sandbox Code Playgroud)

结果:

<Element TreatmentEpisode at 0xffff8f8c8a00>
Run Code Online (Sandbox Code Playgroud)

我所希望的:

TreatmentEpisodes/TreatmentEpisode
Run Code Online (Sandbox Code Playgroud)

...但是,即使我收到了我所希望的,我仍然不确定如何获得每个元素的完整路径。据我了解 XPath 文档,它们仅对“已知”元素名称进行操作。即tree.xpath()似乎需要事先知道元素名称。

Val*_*_Bo 6

从...开始:

import xml.etree.ElementTree as et
Run Code Online (Sandbox Code Playgroud)

解决问题的一个有趣方法是使用iterparse - ElementTree中包含的迭代解析器

它能够报告例如每个解析的元素的每个开始结束事件。有关详细信息,请在 Web 上搜索iterparse的文档/示例。

这个想法是:

  1. 以空列表作为路径开始。
  2. 开始事件中,将元素名称附加到路径并打印到目前为止收集的完整 路径。
  3. 结束事件中,删除path中的最后一个元素。

您甚至可以将此代码包装在生成器函数中:

def pathGen(fn):
    path = []
    it = et.iterparse(fn, events=('start', 'end'))
    for evt, el in it:
        if evt == 'start':
            path.append(el.tag)
            yield '/'.join(path)
        else:
            path.pop()
Run Code Online (Sandbox Code Playgroud)

现在,当你运行时:

for pth in pathGen('Input.xml'):
    print(pth)
Run Code Online (Sandbox Code Playgroud)

您将获得源文件中所有元素的完整路径的打印输出,如下所示:

TreatmentEpisodes
TreatmentEpisodes/TreatmentEpisode
TreatmentEpisodes/TreatmentEpisode/SourceRecordIdentifier
TreatmentEpisodes/TreatmentEpisode/FederalTaxIdentifier
TreatmentEpisodes/TreatmentEpisode/ClientSourceRecordIdentifier
TreatmentEpisodes/TreatmentEpisode
TreatmentEpisodes/TreatmentEpisode/SourceRecordIdentifier
TreatmentEpisodes/TreatmentEpisode/FederalTaxIdentifier
TreatmentEpisodes/TreatmentEpisode/ClientSourceRecordIdentifier
...
Run Code Online (Sandbox Code Playgroud)