我需要解析包含xml注释的文件。具体来说,它是使用MS ///
约定的c#文件。
由此我需要提取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中测试了上面的示例;它可以工作但是(根据我的问题)不会打印任何值)
谢谢!
答案 0 :(得分:2)
我认为Literal('\n')
是你的问题。您不希望使用空格字符构建Literal(因为默认情况下,Literals会在尝试匹配之前跳过空格)。请尝试使用LineEnd()
。
编辑1:
仅仅因为你使用LineEnd获得无限循环并不意味着Literal('\ n')更好。尝试在.setDebug()
定义的末尾添加_eol
,您会发现它永远不会与任何内容匹配。
不要试图将评论的主体定义为“一条或多条不是结束线的行,而是将所有内容都放到行尾”,而不是尝试:
xmlComment = _cPoundOpenXmlComment + pp.SkipTo(_cPoundCloseXmlComment) + _cPoundCloseXmlComment
(你使用LineEnd()获得无限循环的原因是你基本上在做OneOrMore(SkipTo(LineEnd())),但从不使用LineEnd(),所以OneOrMore只是保持匹配和匹配匹配,解析并返回一个空字符串,因为解析位置是 at 行尾。)
答案 1 :(得分:2)
如何使用nestedExpr
:
import pyparsing as pp
text = '''\
///<summary>
/// foobar
///</summary>
blah blah
///<summary> /// bar ///</summary>
///<summary> ///<summary> /// baz ///</summary> ///</summary>
'''
comment=pp.nestedExpr("///<summary>","///</summary>")
for match in comment.searchString(text):
print(match)
# [['///', 'foobar']]
# [['///', 'bar']]
# [[['///', 'baz']]]
答案 2 :(得分: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