使用 Python ElementTree 迭代多个(父、子)节点

2024-04-07

Python (2.6) 的 ElementTree 标准实现不提供从子节点指向父节点的指针。因此,如果需要父母,建议循环父母而不是孩子。

考虑我的 xml 的形式:

<Content>
  <Para>first</Para>
  <Table><Para>second</Para></Table>
  <Para>third</Para>
</Content>

以下查找所有“Para”节点而不考虑父节点:

(1) paras = [p for p in page.getiterator("Para")]

这(改编自 effbot)通过循环遍历父节点而不是子节点来存储父节点:

(2) paras = [(c,p) for p in page.getiterator() for c in p]

这是完全有道理的,并且可以使用条件进行扩展以实现(据称)与(1)相同的结果,但添加了父信息:

(3) paras = [(c,p) for p in page.getiterator() for c in p if c.tag == "Para"]

The ElementTree 文档 http://docs.python.org/release/2.6.4/library/xml.etree.elementtree.html建议 getiterator() 方法进行深度优先搜索。在不查找父级 (1) 的情况下运行它会产生:

first
second
third

然而,从 (3) 中的段落中提取文本,会得到:

first, Content>Para
third, Content>Para
second, Table>Para

这似乎是广度优先的。

因此,这提出了两个问题。

  1. 这是正确且预期的行为吗?
  2. 当子项必须是某种类型但父项可以是任何类型时,如何提取(父项,子项)元组,是否必须维持文件顺序。我不认为运行两个循环并将(3)生成的(父,子)映射到(1)生成的订单是理想的。

考虑一下:

>>> xml = """<Content>
...   <Para>first</Para>
...   <Table><Para>second</Para></Table>
...   <Para>third</Para>
... </Content>"""
>>> import xml.etree.cElementTree as et
>>> page = et.fromstring(xml)
>>> for p in page.getiterator():
...     print "ppp", p.tag, repr(p.text)
...     for c in p:
...         print "ccc", c.tag, repr(c.text), p.tag
...
ppp Content '\n  '
ccc Para 'first' Content
ccc Table None Content
ccc Para 'third' Content
ppp Para 'first'
ppp Table None
ccc Para 'second' Table
ppp Para 'second'
ppp Para 'third'
>>> 

旁白:列表推导式非常出色,直到您想确切地看到正在迭代的内容:-)

getiterator is按照广告顺序生成“ppp”元素。然而,您正在从辅助“ccc”元素中提取您感兴趣的元素,这些元素不符合您想要的顺序。

一种解决方案是进行自己的迭代:

>>> def process(elem, parent):
...    print elem.tag, repr(elem.text), parent.tag if parent is not None else None
...    for child in elem:
...       process(child, elem)
...
>>> process(page, None)
Content '\n  ' None
Para 'first' Content
Table None Content
Para 'second' Table
Para 'third' Content
>>>

现在,您可以在“Para”元素流过时对其父元素(如果有)进行引用,从而捕获每个元素。

这可以很好地封装在生成器小工具中:

>>> def iterate_with_parent(elem):
...     stack = []
...     while 1:
...         for child in reversed(elem):
...             stack.append((child, elem))
...         if not stack: return
...         elem, parent = stack.pop()
...         yield elem, parent
...
>>>
>>> showtag = lambda e: e.tag if e is not None else None
>>> showtext = lambda e: repr((e.text or '').rstrip())
>>> for e, p in iterate_with_parent(page):
...     print e.tag, showtext(e), showtag(p)
...
Para 'first' Content
Table '' Content
Para 'second' Table
Para 'third' Content
>>>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Python ElementTree 迭代多个(父、子)节点 的相关文章

随机推荐

  • 用于电子表格的 Google 应用脚本:如何在脚本管理器中隐藏辅助函数?

    我使用 Google Apps 脚本在 Google 电子表格中自定义了一个菜单 我遇到的问题是 当我按脚本管理器时 我正在使用的所有辅助函数都会列出 我想隐藏它们 我读过如果我在函数名称末尾加下划线 但它不起作用 From documen
  • Ruby 是否像 PHP 一样支持 var 引用?

    在 PHP 中 您可以使两个变量指向相同的数据 a foo b bar a b echo a Outputs bar echo b Outputs bar 我们在 Ruby 中尝试做的事情已经确定 app session等于session
  • 无法使用轨迹球单击列表视图中的视图

    我有一个在行视图中带有可单击按钮的列表视图 以及一个自定义 SimpleCursorAdapter 来实现此列表 尽管单击该行时 onitemclicklistener 没有被触发 请参阅here https stackoverflow c
  • MinGW C 编译器“无法编译简单的测试程序”

    我想将 MinGW 作为 C 编译器运行 MinGW 已从 Chocolatey 安装 调用是通过 CMake 从 gitlab runner 进行的 这失败了 cmake G MinGW Makefiles DCMAKE C COMPIL
  • 通过 Excel VBA 实现 IE11 自动化 - 公司网页

    首先 我对尝试通过 Excel VBA 自动化 IE 还很陌生 话虽这么说 我正在努力自动登录公司特定的网页 仅我们的员工可以访问 目标是自动登录 员工编号 密码并单击 登录 我发现 Firefox 在识别字段方面特别有帮助 所以这就是我在
  • Laravel 翻译 required_if 值

    我正在使用 Laravel 版本 5 2 45 目前我在翻译 required if 规则时遇到一些麻烦 当我使用 required if field value 时 它 会打印错误验证消息中的字段值 在本例中为 1 或 0 这不太可读 例
  • 如何对 LINQ to Objects 查询进行分区?

    这是一个资源分配问题 我的目标是运行查询来获取任何时间段的最高优先级班次 数据集非常大 对于此示例 假设 1000 家公司每个班次有 100 个班次 尽管实际数据集更大 它们都已加载到内存中 我需要对它们运行单个 LINQ to Objec
  • 具有不同图钉颜色的地图视图注释

    我有一个包含 200 多个对象的数组 我试图对每个对象执行循环 每个对象都有一个是 否字段 我想根据该是 否值显示不同颜色的标记 从我所看到的情况来看 我的循环首先遍历每个对象 然后在每个对象的末尾添加所有注释 由于当所有注释都添加到我的地
  • 如何使用 MSAL 对 AAD B2C 进行身份验证?

    我有一个使用 ADAL 的客户端 服务器身份验证的工作版本 但是 当您想要使用本地帐户 即 仅使用用户名或仅使用 AAD 之外没有支持身份验证器的电子邮件地址 时 B2C AAD 似乎无法与 ADAL 很好地配合 看来我们应该用于本地帐户的
  • 参考 Windows Powershell 中的弹出窗口

    我正在为我正在开发的网站进行测试自动化 我正在使用 Windows powershell 创建脚本来执行此操作 我的问题是我需要单击打开另一个窗口的链接 我需要以某种方式引用该窗口 ie new object com InternetExp
  • SQLite 数据到 RecyclerView

    该应用程序的数据存储在 SQLite 数据库中 UI 主要是 RecyclerView 问题是如何最好地将数据从数据库传输到 UI 同时保持主线程的运行 我原本计划使用 CursorLoader ContentProvider 和 Recy
  • 多维数组、可为 null 的引用类型和类型转换

    使用 C 8 的可空引用类型 我们可以编写 对于引用类型 T x T y x 但是 我无法理解多维和锯齿状数组的转换规则 string a new string 1 string b new string 1 string c new st
  • Haskell:ghci 是否显示“Chunk .. Empty”?

    向你学习 Haskell http learnyouahaskell com input and output bytestrings有一个这样的代码示例 ghci gt B pack 99 97 110 Chunk can Empty B
  • Grafana - 是否可以在基于 Loki 的仪表板查询中使用变量?

    我正在 Grafana 上开发基于 Loki 的仪表板 我有一个用于在 Loki 跟踪日志中搜索文本的面板 当前查询如下 job abc service searchTrace json line format if trace messa
  • 获取 rfc7517 格式的 JWKS for Firebase

    我正在使用 Firebase 对我的应用程序中的用户进行身份验证 Firebase 生成一个 JWT 令牌 我需要在我的服务器上对其进行身份验证 我使用 tyk io 来做到这一点 Tyk 支持这些令牌 但要求公钥的数据源位于https w
  • Swagger 将 IFormFile 参数列为“对象”类型

    我有一个控制器 它请求一个包含 IFormFile 作为其属性之一的模型 对于请求描述 Swagger UI 我使用 Swashbuckle 和 OpenApi 3 0 for NET Core 将文件属性的类型列出为类型对象 有没有办法让
  • 为什么 PeekMessage 总是返回 TRUE?

    Main message loop MSG msg ZeroMemory msg sizeof msg while msg message WM QUIT if PeekMessage msg NULL 0U 0U PM REMOVE Tr
  • 将 XSLT 转换作为构建步骤执行

    在 Visual Studio 构建期间 我需要从另一个 XML 文件生成一个 XML 文件 对我来说 很明显 XSLT 模板和转换正是我所需要的 我更喜欢实现此目的的方法是使用项目文件中的 自定义工具 属性 是否已经有一个内置工具可以用于
  • 如何在 Jetpack Compose 中实现这种布局

    我正在尝试使用新的 Jetpack Compose UI 框架 但遇到了问题 我想实现这个布局 在 xml 中很容易实现 但我无法弄清楚如何使垂直分隔线占用可用的垂直空间 而不指定固定的高度 我尝试过的这段代码似乎不起作用 Composab
  • 使用 Python ElementTree 迭代多个(父、子)节点

    Python 2 6 的 ElementTree 标准实现不提供从子节点指向父节点的指针 因此 如果需要父母 建议循环父母而不是孩子 考虑我的 xml 的形式