2011-10-19 102 views
4

我需要解析包含xml注释的文件。具体来说,它是一个使用MS ///惯例的c#文件。pyparsing - 解析xml注释

从这我需要拉出foobar,或/// foobar也是可以接受的。 (注 - 这仍然如果让XML都在同一行不行?)

testStr = """ 
    ///<summary> 
    /// foobar 
    ///</summary> 
    """ 

以下是我有:

import pyparsing as pp 

_eol = pp.Literal("\n").suppress() 
_cPoundOpenXmlComment = Suppress('///<summary>') + pp.SkipTo(_eol) 
_cPoundCloseXmlComment = Suppress('///</summary>') + pp.SkipTo(_eol) 
_xmlCommentTxt = ~_cPoundCloseXmlComment + pp.SkipTo(_eol) 
xmlComment = _cPoundOpenXmlComment + pp.OneOrMore(_xmlCommentTxt) + _cPoundCloseXmlComment 

match = xmlComment.scanString(testStr) 

和输出:

for item,start,stop in match: 
    for entry in item: 
     print(entry) 

但是我并没有在跨多线工作的语法方面取得太大的成功。

(注意 - 我在Python 3.2测试上面的示例,它的工作原理,但(按我的问题)不打印任何值)

谢谢!

回答

2

如何使用nestedExpr

​​
+0

@ PaulMcGuire的解决方案也可以工作,但这正是我应该使用的(这是最简单的......)Thansk! – mike

2

我认为Literal('\n')是你的问题。你不想用空白字符构建Literal(因为在尝试匹配之前,Literals默认跳过空白)。改为使用LineEnd()

编辑1: 仅仅因为你得到LineEnd无限循环并不意味着文字(“\ n”)是更好。尝试在_eol定义的末尾添加.setDebug(),并且您会看到它从不匹配任何内容。

,而不是试图定义您的评论的身体“是不是收线的一行或多行,但得到的一切到最后的行”,如果你只是做:

xmlComment = _cPoundOpenXmlComment + pp.SkipTo(_cPoundCloseXmlComment) + _cPoundCloseXmlComment 

(您使用LineEnd()获得无限循环的原因是您基本上在做OneOrMore(SkipTo(LineEnd())),但从不使用LineEnd(),因此OneOrMore只是保持匹配和匹配以及匹配,解析并返回一个空字符串,因为解析位置是行末。)

+0

感谢您的建议;然而改变为'_eol = pp.LineEnd()。suppress()'会导致hang/inf循环。你可能是更具体的litte(注意 - 将3个部分粘贴在一个.py文件中,代码按原样运行)。谢谢,迈克 – mike

+0

投票了解释什么是错的。咄!我应该看到,我从来没有消耗过行:) – mike

1

您可以使用xml解析器来解析xml。应该很容易提取相关注释行:

import re 
from xml.etree import cElementTree as etree 

# extract all /// lines 
lines = re.findall(r'^\s*///(.*)', text, re.MULTILINE) 

# parse xml 
root = etree.fromstring('<root>%s</root>' % ''.join(lines)) 
print root.findtext('summary') 
# -> foobar 
+0

我以为你在Blade Runner中很棒。 – PaulMcG

+0

@JFSebastian不幸的是,这在我遇到这个问题的大图中是行不通的。是的,我可以按照你的建议提取所有的xml片段,但是我还需要在评论之后解析源代码,并且需要一个语法分析器;逐行执行正则表达式搜索会在文件中添加一个额外的循环。 – mike

+1

@mike:正则表达式只是一个如何提取注释行的例子。在更大的图片中,您使用解析器来提取相关注释(比解析xml更简单的任务),并且不会妨碍您在发现必要时使用xml解析器来解析xml。 – jfs