问题
I want to add external information to ParseResults before return. I return the results of parsing as asXML(). The external data represented as dictionary so as to parsed as XML in the final parsing.
This the code before adding external data from pyparsing import *
# a hypothetical outer parser, with an unparsed SkipTo element
color = oneOf("red orange yellow green blue purple")
expression = SkipTo("XXX") + Literal("XXX").setResultsName('ex') + color.setResultsName('color')
data = "JUNK 100 200 10 XXX green"
print expression.parseString(data).dump()
# main grammar
def minorgrammar(toks):
# a simple inner grammar
integer = Word(nums)
grammar2 = integer("A").setResultsName('A') + integer("B").setResultsName('B') + integer("C").setResultsName('C')
# use scanString to find the inner grammar
# (since we just want the first occurrence, we can use next
# instead of a for loop with a break)
t,s,e = next(grammar2.scanString(toks[0],maxMatches=1))
# remove 0'th element from toks
del toks[0]
# return a new ParseResults, the sum of t and everything
# in toks after toks[0] was removed
return t + toks
grammar1 = expression.setParseAction(minorgrammar)
x = grammar1.parseString(data).asXML("main")
print x
the output is
<main>
<A>100</A>
<B>200</B>
<C>10</C>
<ex>XXX</ex>
<color>green</color>
</main>
the code after adding external data
...
external_data = {'name':'omar', 'age':'40'}
return t + toks + ParseResults(external_data)
grammar1 = expression.setParseAction(minorgrammar)
x = grammar1.parseString(data).asXML("main")
print x
the output
<main>
<A>100</A>
<B>200</B>
<C>10</C>
<ex>XXX</ex>
<color>green</color>
<ITEM>{'age': '40', 'name': 'omar'}</ITEM>
</main>
I want the output in the form
<main>
<A>100</A>
<B>200</B>
<C>10</C>
<ex>XXX</ex>
<color>green</color>
<name>omar</name>
<age>40</age>
</main>
What is the error in that code ? Thans
回答1:
One problem is this fragment:
external_data = {'name':'omar', 'age':'40'}
return t + toks + ParseResults(external_data)
ParseResults will take a dict as a constructor argument, but I don't think it will do what you want - it just assigns the dict as it's 0'th element, and does not assign any results names.
You can assign named values into a ParseResults by using its dict-style assignment:
pr = ParseResults(['omar','40'])
for k,v in external_data.items():
pr[k] = v
See if this gets you closer to your desired format.
EDIT: Hmm, it seems asXML is more fussy about how named results get added to the ParseResults, than just setting the name. This will work better:
def addNamedResult(pr, value, name):
addpr = ParseResults([value])
addpr[name] = value
pr += addpr
And then in your parse action, add the values with their names using:
addNamedResult(toks, 'omar', 'name')
addNamedResult(toks, '40', 'age')
回答2:
Thanks very much Paul. I modified your function to add a dictionary of data
...
external_data = {'name':'omar', 'age':'40'}
return t + toks + addDicResult(external_data)
...
def addDicResult(dict):
pr = ParseResults([])
for k, v in dict.items():
addpr = ParseResults([v])
addpr[k] = v
pr += addpr
return pr
The output
<main>
<A>100</A>
<B>200</B>
<C>10</C>
<ex>XXX</ex>
<color>green</color>
<age>40</age>
<name>omar</name>
</main>
来源:https://stackoverflow.com/questions/11696338/adding-external-information-to-parseresults-before-return