XML に似たファイル (DTD が関連付けられていない) を pyparsing で解析しようとしています。各レコードの一部には、次の内容が含まれています。
- タグ内
<L>
の何か、<L/>
<pc>
and<pc/>
タグ内の 1 つ以上のもの、<MW>
必要に応じて、 and<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
すると、最後の文字列で失敗します (最後から 2 番目の文字列とはスペースのみが異なります)。
pyparsing.ParseException: (at char 47), (line:1, col:48)
を使用するとrecord2
、最後から 2 番目の文字列自体で失敗します。
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 のバグなのか、私のコードのバグなのかはわかりませんが、本当の問題は、必要な種類の文字列をどのように解析するべきかということです。