扩展 pyyaml 以查找和替换 xml ElementTree

Extending pyyaml to find and replace like xml ElementTree

我想扩展 this SO question 来处理一个重要的用例。

背景: pyyaml 非常好用,因为它使用 YAML 和 poops Python-native 数据结构。但是,如果您想在 YAML 中查找特定节点怎么办?引用的问题会建议,嘿,你只知道节点在数据结构中的位置并直接索引到它。事实上,几乎所有关于 SO 上每个 pyyaml 问题的答案似乎都给出了同样的建议。

但是如果事先不知道节点在 YAML 中的位置怎么办?

如果我使用 XML,我会用 xml.etree.ElementTree 解决这个问题。这些为将 XML 文档加载到内存中并根据特定搜索条件查找元素提供了很好的工具。参见 find() and findall()

问题:

  1. pyyaml 是否提供类似于 ElementTree 的搜索功能? (如果是,请随意对我大喊大叫 Google。)
  2. 如果没有,有没有人有扩展 pyyaml 来实现类似事情的好方法? (not 再次遍历反序列化的 YAML 的奖励积分。)

注意 ElementTree 提供的一项重要功能除了能够查找内容外,还能够修改给定元素引用的 XML 文档。我也希望能够在 YAML 上执行此操作。

你知道如何搜索 python 对象吗?那么您就知道如何搜索 yaml.load()...

的结果

YAML 在两个重要方面不同于 XML:一个是虽然 XML 中的每个元素都有一个标签和一个值,但在 YAML 中,有些东西可能只是值.但其次......同样,YAML 创建 python 个对象。没有可以使用的中间内存格式。

如果您像这样加载 YAML 文件:

- First
- Second
- Third

您会得到一个类似于 ['First', 'Second', 'Third'] 的列表。想找到 'Third' 却不知道它在哪里?您可以使用 [x for x in my_list if 'Third' in x] 找到它。需要在字典中查找项目?去做就对了。

如果你想修改一个对象,你不修改 YAML,你修改对象。例如。现在我希望第二个条目是德语。我只是做 'my_list[1] = 'zweite',就地修改它。现在 python 列表看起来像 ['First', 'zweite', 'Third'],将它转储到 YAML 看起来像

- First
- zweite
- Third

请注意,PyYAML 非常智能...您甚至可以使用循环创建对象:

>>> a = [1,2,3]
>>> b = {}
>>> b[1] = a
>>> b[2] = a
>>> print yaml.dump(b)
1: &id001 [1, 2, 3]
2: *id001
>>> b[2] = [3,4,5]
>>> print yaml.dump(b)
1: [1, 2, 3]
2: [3, 4, 5]

在第一种情况下,它甚至发现 b[1]b[2] 指向同一个对象,所以它创建了 links 并自动放置了一个 link从一个到另一个...在原始对象中,如果您执行类似 a.pop() 的操作,b[1]b[2] 都会显示一个条目已消失。如果将该对象发送到 YAML,然后将其重新加载,那将 仍然 为真。

(请注意在第二个中,它们不相同,PyYAML 不会创建额外的符号,因为它不需要)。

简而言之:您很可能只是想多了。

问题 1 的答案是:否。 PyYAML 实现了 YAML 1.1 语言标准,并且没有任何关于通过标准或库中的任何路径查找标量的方法。

但是,如果您安全加载 YAML 结构,则一切都是映射、序列或标量。即使是这样一个简单的表示(简单,与 !typemarkers 的完整对象实例化相比),已经可以包含递归自引用结构:

&a x: *a 

如果没有外部语义解释,这在 XML 中是不可能的。这使得在 YAML 中制作通用树遍历器比在 XML 中更难。 YAML 的类型加载机制也使得泛型 tree walker 变得更加困难,即使你排除了自引用的问题。

如果你事先不知道节点所在的位置,你仍然需要知道如何识别节点,因为你不知道如何去父节点(可能表示为多个组合映射和序列层,拥有一个依赖于上下文的通用机制几乎是无用的。

如果不能依赖上下文(通常),剩下的就是一个唯一可识别的值(如 HTML id 属性)。如果 YAML 中的所有对象都有这样一个唯一的 ID,那么就可以在(安全加载的)树中搜索这样一个 ID 值,并提取它下面的任何结构(映射、序列),直到你找到一个叶子(标量)或一些具有自己的 ID 的结构(另一个对象)。

我关注 YAML 开发已经有一段时间了(我的 YAML 文件夹中来自 YAML 邮件列表的最早电子邮件来自 2004 年),从那以后我没有看到任何通用的发展。我确实有一些工具可以遍历树并找到我用来提取部分简化结构以测试我的 raumel.yaml 库的东西,但是没有可发布的代码(如果它已经在 PyPI 上了)它是),并且没有像您可以为 XML 做出的通用解决方案(这是 IMO,就其本身而言,在语法上不如 YAML 复杂)。