2013-05-20 76 views
5

我剛開始使用pyparsing這個晚上,我已經建立了一個複雜的語法,它描述了一些資源,我用非常有效地工作。這非常簡單而且非常強大。不過,我在使用ParsedResults時遇到了一些麻煩。我需要能夠遍歷嵌套標記的順序來他們發現,而且我發現它有點沮喪。我抽象我的問題,以一個簡單的例子:`pyparsing`:迭代`ParsedResults`

import pyparsing as pp 

word = pp.Word(pp.alphas + ',.')('word*') 
direct_speech = pp.Suppress('「') + pp.Group(pp.OneOrMore(word))('direct_speech*') + pp.Suppress('」') 
sentence = pp.Group(pp.OneOrMore(word | direct_speech))('sentence') 

test_string = 'Lorem ipsum 「dolor sit」 amet, consectetur.' 

r = sentence.parseString(test_string) 

print r.asXML('div') 

print '' 

for name, item in r.sentence.items(): 
    print name, item 

print '' 

for item in r.sentence: 
    print item.getName(), item.asList() 

據我所看到的,這應該工作?下面是輸出:

<div> 
    <sentence> 
    <word>Lorem</word> 
    <word>ipsum</word> 
    <direct_speech> 
     <word>dolor</word> 
     <word>sit</word> 
    </direct_speech> 
    <word>amet,</word> 
    <word>consectetur.</word> 
    </sentence> 
</div> 

word ['Lorem', 'ipsum', 'amet,', 'consectetur.'] 
direct_speech [['dolor', 'sit']] 

Traceback (most recent call last): 
    File "./test.py", line 27, in <module> 
    print item.getName(), item.asList() 
AttributeError: 'str' object has no attribute 'getName' 

XML輸出似乎表明該字符串完全解析,我會想,但我不能遍歷句子,例如,重建它。

有沒有辦法做我需要?

謝謝!

編輯:

我一直在使用這樣的:

for item in r.sentence: 
    if isinstance(item, basestring): 
     print item 
    else: 
     print item.getName(), item 

,但它並不能幫助我所有的東西,因爲我不能區分不同類型的字符串。這裏有一個稍微擴展案例:

word = pp.Word(pp.alphas + ',.')('word*') 
number = pp.Word(pp.nums + ',.')('number*') 

direct_speech = pp.Suppress('「') + pp.Group(pp.OneOrMore(word | number))('direct_speech*') + pp.Suppress('」') 
sentence = pp.Group(pp.OneOrMore(word | number | direct_speech))('sentence') 

test_string = 'Lorem 14 ipsum 「dolor 22 sit」 amet, consectetur.' 

r = sentence.parseString(test_string) 

for i, item in enumerate(r.sentence): 
    if isinstance(item, basestring): 
     print i, item 
    else: 
     print i, item.getName(), item 

輸出爲:

0 Lorem 
1 14 
2 ipsum 
3 word ['dolor', '22', 'sit'] 
4 amet, 
5 consectetur. 

沒有太大的幫助。我不能wordnumber區分,並且direct_speech元素標記word?!

我顯然失去了一些東西。我想要做的全部是:

for item in r.sentence: 
    if (item is a number): 
     do something 
    elif (item is a word): 
     do something else 
etc. ... 

我應該以不同的方式接近嗎?

回答

1

很好,我已經嘗試了許多不同的方法,現在我無法得到我所需要的,所以(荒誕但它似乎),我使用.asXML()和解析由此產生的XML。這是我的例子:

import pyparsing as pp 

word = pp.Word(pp.alphas + ',.')('word*') 
number = pp.Word(pp.nums + ',.')('number*') 
direct_speech = pp.Suppress('「') + pp.Group(pp.OneOrMore(word | number))('direct_speech*') + pp.Suppress('」') 
sentence = pp.Group(pp.OneOrMore(word | number | direct_speech))('sentence') 

test_string = 'Lorem 14 ipsum 「dolor 22 sit」 amet, consectetur.' 
r = sentence.parseString(test_string) 

from lxml import etree 
xml = etree.fromstring(r.sentence.asXML('sentence')) 
for el in xml: 
    if len(el): 
     print el.tag 
     for sub_el in el: 
      print ' ', sub_el.tag, ':', sub_el.text 
    else: 
     print el.tag, ':', el.text 

,輸出:

word : Lorem 
number : 14 
word : ipsum 
direct_speech 
    word : dolor 
    number : 22 
    word : sit 
word : amet, 
word : consectetur. 

好像房前屋後很長的路要走,但似乎沒有更好的辦法。

5

r.sentence包含字符串和ParseResults的組合,只有ParseResults支持getName()。你有沒有試過迭代r.sentence?如果我把它打印出來使用asList(),我得到:

['Lorem', 'ipsum', ['dolor', 'sit'], 'amet,', 'consectetur.'] 

還是這個片斷:

for item in r.sentence: 
    print type(item),item.asList() if isinstance(item,pp.ParseResults) else item 

給出:

<type 'str'> Lorem 
<type 'str'> ipsum 
<class 'pyparsing.ParseResults'> ['dolor', 'sit'] 
<type 'str'> amet, 
<type 'str'> consectetur. 

我不知道我回答你的問題,但是這是否能夠揭示下一步的發展方向?

(歡迎Pyparsing)