首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何合并两个lxml.objectify元素?

如何合并两个lxml.objectify元素?
EN

Stack Overflow用户
提问于 2017-04-27 15:23:41
回答 1查看 538关注 0票数 0

我正在解析一些XML配置以使用其中的设置。我不打算再写出XML,所以我在这里只对提取感兴趣。

我有两个lxml.objectify元素:一方面是包含默认全局设置的元素,另一方面是包含特定于实例的设置的元素。每个元素都有类似的结构(例如,root.global_settings.lights包含与root.instance_settings.lights相同的设置),但可以存在交集和集合差异。元素包含一些子文本节点,但也包含包含其他节点的节点。

我想要的是:包含两个元素的所有设置的单个元素。特定于实例的设置会覆盖全局设置。

我目前最好的解决方案是遍历实例子实例,并覆盖/添加到全局实例子实例(在有文本节点的所有级别)。我在想也许会有更像dict.update的东西?

编辑:举个例子

代码语言:javascript
复制
<global>
    <birthday>Unknown</birthday>
    <wishes>
        <cake>Chocolate</cake>
        <gift>Book</gift>
    </wishes>
</global>

<instance>
    <name>Mike</name>
    <birthday>06-06-1974</birthday>
    <wishes>
        <notes>Hates flowers</notes>
    </wishes>
<instance>

将产生的结果与我在上面运行objectify.parse时的结果相同

代码语言:javascript
复制
<global>
    <name>Mike</name>
    <birthday>06-06-1974</birthday>
    <wishes>
        <cake>Chocolate</cake>
        <gift>Book</gift>
        <notes>Hates flowers</notes>
    </wishes>
</global>
EN

回答 1

Stack Overflow用户

发布于 2017-05-24 01:56:50

我没有找到任何原生的lxml解决方案。Objectify元素具有字典(你可以像字典一样访问它们的值)和列表(你可以用其他元素扩展和追加一个元素)的特征。然而,Update根本不起作用,extend有严重的局限性,包括缺乏递归性。

所以我把这个递归函数放在一起,它使用一个元素更新另一个元素。这里的特定上下文是使用用户设置覆盖默认设置,在没有用户设置的地方保留默认设置。

本质上,该函数区分由两个特征定义的四种节点:

1)默认设置中是否缺少该节点?如果是这样,我们可以直接复制(附加)给用户。

2)如果节点也在默认设置中,我们需要进一步区分:它是DataElement -即具有直接数据值的节点,例如<name>Mike</name> -还是更多没有直接数据值的“结构化”节点,例如上例中的<wishes>...</wishes>。在第一种情况下,我们将默认节点(和值)替换为用户节点。在第二个步骤中,我们需要深入一层,重复整个过程。

代码语言:javascript
复制
def merge(user_el, default_el):
    '''Updating one lxml objectify elements with another'''
    for child in user_el.iterchildren():
        default_child = default_el.find(child.tag)
        if default_child is None:
            default_el.append(child)
            continue
        if isinstance(child, objectify.ObjectifiedDataElement):
            default_el.replace(default_child, child)
        elif isinstance(child, objectify.ObjectifiedElement):
            merge(child, default_child)

编辑:上面的测试让我意识到,如果在默认情况下也存在的结构化用户元素,例如作为一个空节点,有多个具有相同标记名称的子节点,它们将逐渐替换彼此的数据子节点。为了避免这种情况,我创建了一个可以编辑默认设置副本的版本。这样,我们继续检查空的占位符元素,而不是我们逐渐填充的元素。

代码语言:javascript
复制
new_xml = copy.deepcopy(DEFAULT_XML)
merge(user_xml, new_xml, DEFAULT_XML)

def merge(user_el, new_el, default_el):
   '''Updating one lxml objectify elements with another'''
   for child in user_el.iterchildren():
       new_child = new_el.find(child.tag)
       default_child = default_el.find(child.tag)
       if default_child is None:
           new_el.append(child)
           continue
       if isinstance(child, objectify.ObjectifiedDataElement):
           new_el.replace(new_child, child)
       elif isinstance(child, objectify.ObjectifiedElement):
           merge(child, new_child, default_child)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43651171

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档