首页 > 解决方案 > 如何遍历 LXML etree 并创建 XML 的方案

问题描述

我有自己的班级来代表NodeXML。我正在寻找一种方法来生成scheme- 具有所有标签和属性的最小树。

通过方案,我的意思是一棵树,其中所有标签只出现一次,每个标签都具有所有可能的属性和子项。

因此,如果root有多个product孩子,其中第一个product有属性name="some name"但没有孩子,最后一个product有属性class="someclass"和一个孩子image,方案树将有一个root有一个孩子product,有两个属性nameclass一个孩子image

class SchemeNode():

    def __init__(self, tag=None, text=None, parent=None, many=False, attrs=None):
        self.tag = tag
        self.text = text
        self.parent: Node = parent
        self.children = set()
        self.many = many
        self.attrs = attrs if attrs else {} # name, class etc...

    @property
    def siblings(self):
        return self.parent.children

    def add_child(self, child):
        child.parent = self
        self.children.add(child)

    def __str__(self):
        return f'Node [{self.tag}]'

我创建了一个SchemeNodeService最终会创建这样的方案的方案,但它提出了max recursion exceeded,我认为有一种更优雅的方法可以做到这一点。

也许BFS会更好?

class SchemeNodeService:
    @classmethod
    def load_xml(cls, path):
        with open(path, 'rb') as f:
            root = etree.fromstring(f.read(), parser=etree.XMLParser())
            return cls.load_node(root)

    @classmethod
    def load_node(cls, lxml_node, parent=None):
        node = SchemeNode(lxml_node.tag, lxml_node.text, parent, attrs=lxml_node.attrib)
        for lxml_child in lxml_node.getchildren():
            node.add_child(cls.load_node(lxml_child, node))
        return node

    @classmethod
    def generate_scheme_node(cls, tag, nodes, parent):
        attrs = cls._reduce_attrs(nodes)
        snode = SchemeNode(tag=tag, parent=parent, attrs=attrs)
        children = x.children
        children_grouped = itertools.groupby(children, lambda x: getattr(x, 'tag'))
        for tag, group in children_grouped:
            snode_child = cls.generate_scheme_node(tag, group, snode)
            snode.add_child(snode_child)
        return snode

    @classmethod
    def _reduce_attrs(cls, nodes):
        # todo assert all nodes same tag
        attrs = {}
        for node in nodes:
            attrs.update(node.attrs)
        return attrs

标签: pythonxmltreelxmltree-traversal

解决方案


推荐阅读