Judge whitespace or number using pyparsing

Viewed 23

I am working on parsing structured text files by pyparsing and I have a problem judging whitespace or numerical number. My file looks like this:

RECORD   0001
TITLE    (Main Reference Title)
AUTHOR   (M.Brown)

Some files have more than one author then

RECORD   0002
TITLE    (Main Reference Title 1)
AUTHOR  1(S.Red)
        2(B.White)

I would like to parse files and convert them into dictionary format.

{"RECORD": "001",
 "TITLE": "Main Reference Title 1",
 "AUTHOR": {"1": "M.Brown"}
}
{"RECORD": "002",
 "TITLE": "Main Reference Title 2",
 "AUTHOR": {"1": "S.Red", "2": "B.White"}
}

I tried to parse the AUTHOR field by pyparsing (tried both 2.4.7 and 3.0.0b3). Following is the simplified version of my code.

from pyparsing import *
flag = White(" ",exact=1).set_parse_action(replace_with("1")) | Word(nums,exact=1)
flaged_field     = Group(flag + restOfLine)
next_line        = White(" ",exact=8).suppress() + flaged_field

authors_columns  = Keyword("AUTHOR").suppress() +\
                   White(" ",exact=2).suppress() +\.
                   flaged_field +\        # parse first row 
                   ZeroOrMore(next_line)  # parse next row

authors       = authors_columns.search_string(f)

, where 'f' contains all lines read from the file. With this code, I only could parse the author's names with numbering flags.

[]
[[['1', '(S.Red)'],['2','(B.White)']]]

However, if I only parse with whitespace

flag = White(" ",exact=1).set_parse_action(replace_with("1"))

it worked correctly for the files without numbering flags.

['1', '(M.Brown)']
[]

The number (or whitespace) in [9:10] has a meaning in my format and want to judge if it is a whitespace or a numerical number (limited up to 9). I also replaced "|" to "^", and replaced the order, and tried

flag  = Word(nums+" ")

, too, but neither of the cases works for me. Why judge White(" ") or Word(nums) doesn't work with my code? Could someone help me or give me an idea to solve this?

1 Answers

This was solved by adding leave_whitespace().

flag                    = (White(" ",exact=1).set_parse_action(replace_with("0")) | Word(nums,exact=1)).leave_whitespace() 
Related