python - 如何遍历 LXML etree 并创建 XML 的方案
问题描述
我有自己的班级来代表Node
树XML
。我正在寻找一种方法来生成scheme
- 具有所有标签和属性的最小树。
通过方案,我的意思是一棵树,其中所有标签只出现一次,每个标签都具有所有可能的属性和子项。
因此,如果root
有多个product
孩子,其中第一个product
有属性name="some name"
但没有孩子,最后一个product
有属性class="someclass"
和一个孩子image
,方案树将有一个root
有一个孩子product
,有两个属性name
和class
一个孩子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
解决方案
推荐阅读
- c++ - const对象的容器?
- tensorflow - 使用flow_from_directory时如何获取混淆矩阵和ROC曲线?
- reactjs - 无法删除 useRef
设置反应离子时的值 - php - 用php从mysql列数据中分离值
- python - 运行相同网格搜索代码的不同超参数
- c - 我无法弄清楚为什么我的这部分代码没有运行,当它自己运行时就好了
- machine-learning - 处理丢失的数据而不泄露未来的观察结果
- python - 对齐 QScrollArea
- asp.net - Dotnet Blazor 在 Digital Ocean 上部署错误:无法检索有关进程或线程的指定信息
- python - how to create variable containing the age of another row inside a common id in Python 3.8?