使用 setResultsName() 和 asXML() 进行 PyParsing 时标记错误

Tag error when PyParsing using setResultsName() and asXML()

我想使用 PyParsing 来解析文本并输出为 XML (asXML())。但是 XML 输出中的标签与 setResultsName.

不一致

请看以下代码段:

p1 = (Literal('a').setResultsName('tag_a')).setResultsName('tag_out')
print(p1.parseString('a').asXML())
# Output:
# <tag_out>
#   <tag_out>a</tag_out>
# </tag_out>

p2 = (Literal('a').setResultsName('tag_a') +
      Literal('b').setResultsName('tag_b')).setResultsName('tag_out')
print((p2.parseString('a b').asXML()))

# The result is randomly chosen from these two outputs.
# <tag_out>
#   <tag_a>a</tag_a>
#   <tag_b>b</tag_b>
# </tag_out>
#
# <tag_out>
#   <tag_out>a</tag_out>
#   <tag_b>b</tag_b>
# </tag_out>

注意第一个内部元素的标签经常是错误的。

这是 PyParsing 的已知错误吗? patch/workaround 是什么?

Pyparsing 不会根据您的代码自动为语法中的表达式赋予结构。这是设计使然,因此可以轻松地将部分表达式合并在一起,因此:

grammar = exprA + exprB + exprC

grammar = exprA + (exprB + exprC)

tmp = exprA + exprB
grammar = tmp + exprC

行为相同。因此,仅仅将 () 放在表达式周围并不会自动定义语法的另一个级别。

Pyparsing 提供了 Group class 你想要的。如果您将代码更改为:

,您的结果将会大大改善
p1 = Group(Literal('a').setResultsName('tag_a')).setResultsName('tag_out')
print(p1.parseString('a').asXML())

p2 = Group(Literal('a').setResultsName('tag_a') +
      Literal('b').setResultsName('tag_b')).setResultsName('tag_out')
print((p2.parseString('a b').asXML()))

话虽如此,asXML() 并不是 pyparsing 的最大部分,因为它必须在某些情况下在遍历结构和创建输出标签时进行猜测。如果这只是为了调试目的,我建议改用 dump() 方法。

我还建议您切换到 setResultsName 的隐式可调用形式 - 我认为它可以在不影响可读性的情况下简化您的语法代码。查看区别:

p1 = Group(Literal('a')('tag_a'))('tag_out')
print(p1.parseString('a').asXML())

p2 = Group(Literal('a')('tag_a') + Literal('b')('tag_b'))('tag_out')
print((p2.parseString('a b').asXML()))