如何从pyparsing转发对象获得结果?

2024-10-06 11:31:11 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我们有下面的字符串

string = """
object obj1{
    attr1 value1;


    object obj2 {
        attr2 value2;
    }
}

object obj3{
    attr3 value3;
    attr4 value4;
}

"""

有一个嵌套的对象,我们使用Forward来解析它。在

^{pr2}$

这就是结果。这个对象.asXML()函数包含所有的信息,但是由于它已被展平,因此信息的顺序对于解析结果至关重要。这是最好的办法吗?我一定错过了什么。我想要一个既适用于嵌套对象又适用于非嵌套对象的解决方案,即obj1、obj2和obj3。在

另外,setResultsName('object_type')不返回父对象的object_type。上面程序的输出如下所示。有什么建议吗?在

Enumerating over object 0

This is the object type obj2

<ITEM>
  <object_type>obj1</object_type>
  <name>attr1</name>
  <value>value1</value>
  <object_type>obj2</object_type>
  <name>attr2</name>
  <value>value2</value>
</ITEM>
{'object_type': 'obj2', 'name': 'attr2', 'value': 'value2'}
['obj1', 'attr1', 'value1', 'obj2', 'attr2', 'value2']
['obj1', 'attr1', 'value1', 'obj2', 'attr2', 'value2']
['obj1', 'attr1', 'value1', 'obj2', 'attr2', 'value2']
- name: attr2
- object_type: obj2
- value: value2


Enumerating over object 1


This is the object type obj3

<ITEM>
  <object_type>obj3</object_type>
  <name>attr3</name>
  <value>value3</value>
  <name>attr4</name>
  <value>value4</value>
</ITEM>
{'object_type': 'obj3', 'name': 'attr4', 'value': 'value4'}
['obj3', 'attr3', 'value3', 'attr4', 'value4']
['obj3', 'attr3', 'value3', 'attr4', 'value4']
['obj3', 'attr3', 'value3', 'attr4', 'value4']
- name: attr4
- object_type: obj3
- value: value4

Tags: nameobjectvaluetypevalue1attr1value2attr2
2条回答

我可以通过在setResultsNames函数中使用listAllMatches=True来解决这个问题。这给了我asXML()结果,它的结构可以从中检索信息。它仍然依赖于XML的顺序,并且需要使用zip来获得name和{}的attribute。我把这个问题留着,看看有没有更好的方法。在

当您成功地处理了输入字符串之后,让我建议您对语法进行一些改进。在

在定义递归语法时,通常需要在输出结果中保持某种结构。在您的例子中,结构的逻辑部分是每个对象的内容,它由左括号和右大括号包围。概念上:

object_content = '{' + ZeroOrMore(attribute_defn | object_defn) + '}'

那么支持表达式只是(仍在概念上):

^{pr2}$

实际的Python/pyparsing如下所示:

LBRACE,RBRACE,SEMI = map(Suppress, "{};")

word = Word(alphas, alphanums)
attribute = word

# expand to include other values if desired, such as ints, reals, strings, etc.
attribute_value = word 
attributeDefn = Group(word("name") + value("value") + SEMI)

OBJECT = Keyword("object")
object_header = OBJECT + word("object_name")
object_grammar = Forward()
object_body = Group(LBRACE 
                    + ZeroOrMore(object_grammar | attributeDefn)
                    + RBRACE)
object_grammar <<= Group(object_header + object_body("object_content"))

Group为我们做了两件事:它将结果构造成子对象;它使一个级别的结果名称不与另一个级别的结果名称发生冲突(因此不需要listAllMatches)。在

现在,您可以使用scanString处理输入,而不是scanString

print(OneOrMore(object_grammar).parseString(string).dump())

给予:

[['object', 'obj1', [['attr1', 'value1'], ['object', 'obj2', [['attr2', 'value2']]]]], ['object', 'obj3', [['attr3', 'value3'], ['attr4', 'value4']]]]
[0]:
  ['object', 'obj1', [['attr1', 'value1'], ['object', 'obj2', [['attr2', 'value2']]]]]
  - object_content: [['attr1', 'value1'], ['object', 'obj2', [['attr2', 'value2']]]]
    [0]:
      ['attr1', 'value1']
      - name: attr1
      - value: value1
    [1]:
      ['object', 'obj2', [['attr2', 'value2']]]
      - object_content: [['attr2', 'value2']]
        [0]:
          ['attr2', 'value2']
          - name: attr2
          - value: value2
      - object_name: obj2
  - object_name: obj1
[1]:
  ['object', 'obj3', [['attr3', 'value3'], ['attr4', 'value4']]]
  - object_content: [['attr3', 'value3'], ['attr4', 'value4']]
    [0]:
      ['attr3', 'value3']
      - name: attr3
      - value: value3
    [1]:
      ['attr4', 'value4']
      - name: attr4
      - value: value4
  - object_name: obj3

我开始只是对你的代码做一些简单的修改,但是你的原始代码有一个致命的缺陷。您的解析器将左大括号和右大括号分隔成两个单独的表达式—虽然这样“有效”,但它无法定义结果的组结构。在

相关问题 更多 >