我正在尝试使用 pyparsing 解析类似 XML 的文件(没有关联的 DTD)。每个记录看起来的一部分有以下内容:
- 里面的东西
<L>
和<L/>
标签, <pc>
和<pc/>
标签内的一件或多件事情,- 可选地,在
<MW>
和<MW/>
标签内的东西, - 可选地,一个字面量
<mul/>
,并且可选地一个字面量<mat/>
这些元素的顺序各不相同。
所以我写了以下内容(我是pyparsing的新手;请指出我是否在做一些愚蠢的事情):
#!/usr/bin/env python
from pyparsing import *
def DumbTagParser(tag):
tag_close = '</%s>' % tag
return Group(
Literal('<') + Literal(tag).setResultsName('tag') + Literal('>')
+ SkipTo(tag_close).setResultsName('contents')
+ Literal(tag_close)
).setResultsName(tag)
record1 = Group(ZeroOrMore(DumbTagParser('pc'))).setResultsName('pcs') &\
DumbTagParser('L') & \
Optional(Literal('<mul/>')) & \
Optional(DumbTagParser('MW')) & \
Optional(Literal('<mat/>'))
record2 = Group(ZeroOrMore(DumbTagParser('pc'))).setResultsName('pcs') &\
Optional(DumbTagParser('MW')) & \
Optional(Literal('<mul/>')) & \
DumbTagParser('L')
def attempt(s):
print 'Attempting:', s
match = record1.parseString(s, parseAll = True)
print 'Match: ', match
print
attempt('<L>1.1</L>')
attempt('<pc>Page1,1</pc> <pc>Page1,2</pc> <MW>000001</MW> <L>1.1</L>')
attempt('<mul/><MW>000003</MW><pc>1,1</pc><L>3.1</L>')
attempt('<mul/> <MW>000003</MW> <pc>1,1</pc> <L>3.1</L> ') # Note end space
解析器record1
都record2
失败了,但有不同的例外。使用record1
,它在最后一个字符串上失败(与倒数第二个字符串仅在空格中不同):
pyparsing.ParseException: (at char 47), (line:1, col:48)
并且record2
,它在倒数第二个字符串本身上失败:
pyparsing.ParseException: Missing one or more required elements (Group:({"<" "L" ">" SkipTo:("</L>") "</L>"})) (at char 0), (line:1, col:1)
现在奇怪的是,如果我在 的定义中交换第 2 行和第 3 行record2
,那么它解析得很好!
record2 = Group(ZeroOrMore(DumbTagParser('pc'))).setResultsName('pcs') &\
Optional(Literal('<mul/>')) & \
Optional(DumbTagParser('MW')) & \
DumbTagParser('L') # parses my example strings fine
(是的,我意识到它record2
不包含任何规则<mat/>
。我试图获得一个反映这种对重新排序的敏感性的最小示例。)
我不确定这是否是 pyparsing 或我的代码中的错误,但我真正的问题是我应该如何解析我想要的字符串类型。