Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的解析字典_Python_Xml_Python 3.x - Fatal编程技术网

python中的解析字典

python中的解析字典,python,xml,python-3.x,Python,Xml,Python 3.x,我有一个XML,它在解析时提供了具有父子关系的字典 import xml.etree.ElementTree as ET def remove_value(listOfDicts, key): for subVal in listOfDicts: if key in subVal: del subVal[key] def get_children(parent): for child in parent: if "AC

我有一个XML,它在解析时提供了具有父子关系的字典

 import xml.etree.ElementTree as ET

def remove_value(listOfDicts, key):
    for subVal in listOfDicts:
        if key in subVal:
            del subVal[key]

def get_children(parent):
    for child in parent:
        if "ACTION" in child.tag:
            continue
        if 'BOOLOP' in child.attrib:
            yield child.attrib['BOOLOP']
        else:
            yield child.attrib


def get_parent_children_mapping(tree):
    return { parent: list(get_children(parent)) for parent in tree.iter() if "ACTION" not in parent.tag }

s = """
  <RULE COMMENT="" DEFAULTPRIORITY="50" DESCRIPTION="DefaultShipping" DISABLEFLG="N" DefinedOutsideTree="true" FIRINGPHASE="" NAME="DefaultShipping" PATH="PB.SMB.DefaultShipping" RULECLASSIFICATION="PICK" TRIGGER="1">
            <BOOLOP BOOLOP="and" SEQ="0" TYPE="0">
                <BOOLOP BOOLOP="or" SEQ="1" TYPE="0">
                    <FRAGMENT FUNC1="value" FUNC2="propval" NULLACTION="Fragment is false" OP="=" PROP1="DEFAULT_SKU1" PROP2="_sku" SEQ="1" TYPE="1"/>
                    <FRAGMENT FUNC1="value" FUNC2="propval" NULLACTION="Fragment is false" OP="=" PROP1="DEFAULT_SKU2" PROP2="_sku" SEQ="2" TYPE="1"/>
                    <FRAGMENT FUNC1="value" FUNC2="propval" NULLACTION="Fragment is false" OP="=" PROP1="DEFAULT_SKU3" PROP2="_sku" SEQ="3" TYPE="1"/>
                </BOOLOP>
                <FRAGMENT FUNC1="propval" FUNC2="literal" NULLACTION="Fragment is false" OP="=" PROP1="_amEntitled" PROP2="1" SEQ="2" TYPE="1"/>
                <BOOLOP BOOLOP="and" SEQ="3" TYPE="0">
                    <FRAGMENT FUNC1="value" FUNC2="literal" NULLACTION="Fragment is true" OP="!=" PROP1="IsShipingSelected" PROP2="yes" SEQ="1" TYPE="1"/>
                    <FRAGMENT FUNC1="value" FUNC2="literal" NULLACTION="Fragment is true" OP="!=" PROP1="IsShipingSelected" PROP2="no" SEQ="2" TYPE="1"/>
                </BOOLOP>
            </BOOLOP>
            </RULE>
"""
entries = ['NULLACTION','SEQ','TYPE']
tree = ET.fromstring(s)
for parent, children in get_parent_children_mapping(tree).items():
    if children:
        for vals in entries:
            remove_value(children, vals)
        if 'NAME' in parent.attrib:
            print("{0} : {1}".format(parent.attrib['NAME'], children))


        elif 'BOOLOP' in parent.attrib:
            print("{0} : {1}".format(parent.attrib['BOOLOP'], children))

        else:
            print("{0} : {1}".format(parent.tag, children))
输出描述了父子关系。现在我想进一步操作输出,如下所示:

(FUNC1(PROP1)操作FUNC2(PROP2)和FUNC1(PROP1)操作FUNC2(PROP2))或(FUNC1(PROP1)操作FUNC2(PROP2))

解析器中是否有内置的东西,或者我是否需要编写自己的解析器。感谢您的帮助

注意

在我的输出示例中,FUNC1、FUNC2、PROP1等表示它们的值


感谢@Martijn Pieters对语法树的指导

不,没有内置解析器,也不需要解析器。您需要构建一个,这并不难:

from dataclasses import dataclass, field, fields
from typing import List

@dataclass
class Node:
    seq: int
    type: int

    @classmethod
    def tree_from_xml(cls, node):
        name = node.tag
        for cls in cls.__subclasses__():
            if cls.__name__.upper() == name:
                return cls.node_from_xml(node)

    @classmethod
    def node_from_xml(cls, node, **kwargs):
        fieldargs = {f.name: node.attrib.get(f.name.upper()) for f in fields(cls)}
        fieldargs['seq'] = int(fieldargs['seq'])
        fieldargs['type'] = int(fieldargs['type'])
        fieldargs.update(kwargs)
        return cls(**fieldargs)

@dataclass
class BoolOp(Node):
    boolop: str
    operands: List[Node] = field(default_factory=list)

    def __str__(self):
        joined = f' {self.boolop} '.join(map(str, self.operands))
        return f'({joined})'

    @classmethod
    def node_from_xml(cls, node):
        operands = (Node.tree_from_xml(child) for child in node)
        return super().node_from_xml(node, operands=[op for op in operands if op])

@dataclass
class Fragment(Node):
    func1: str
    func2: str
    nullaction: str
    op: str
    prop1: str
    prop2: str

    def __str__(self):
        return f'{self.func1}({self.prop1}) {self.op} {self.func2}({self.prop2})'
然后从顶级
BOOLOP
XML节点构建这些对象,并打印结果:

rule = Node.tree_from_xml(tree.find('.//BOOLOP'))
print(rule)
请注意,
规则
是一个
节点
子类,因此您仍然可以直接检查树,或者对该对象调用
str()
,以获得字符串转换

演示:


这正是我想要的。我肯定会阅读更多关于语法树的内容。我只有一个问题。这是我的网站的链接。我这样做是因为我需要找到迭代规则标签并获得所有属性集(即规则定义),然后根据项目中附加的属性找到触发的属性。但是感谢您的帮助。从上周开始,我一直在努力实现这一目标。起初,我甚至尝试将xml转换为JSON,但这是一项痛苦的工作。所以我又回到了xml@Duck_dragon正确的;通过将规则结构保持为树,您可以根据需要向这些节点添加功能,或者添加更多节点以覆盖更多XML标记,这一切都取决于您的最终目标。例如,如果您需要将规则与一组特定的值进行匹配,那么添加对每个规则求值的功能是有意义的。如果我写入
findall而不是find,则会出现错误
AttributeError:'list'对象没有属性“tag”
。基本上,我需要根据某些标准获得所有规则。我在我的数据库中只有经过编辑的代码question@Duck_dragon基本思想是表达式是层次结构,如果需要对其进行推理,则使用包含节点的节点树结构可以简化工作,特别是当这些节点是具有功能的类时。
rule = Node.tree_from_xml(tree.find('.//BOOLOP'))
print(rule)
>>> rule = Node.tree_from_xml(tree.find('.//BOOLOP'))
>>> print(rule)
((value(DEFAULT_SKU1) = propval(_sku) or value(DEFAULT_SKU2) = propval(_sku) or value(DEFAULT_SKU3) = propval(_sku)) and propval(_amEntitled) = literal(1) and (value(IsShipingSelected) != literal(yes) and value(IsShipingSelected) != literal(no)))