4

我需要解析一个包含 xml 注释的文件。具体来说,它是使用 MS///约定的 ac# 文件。

从此我需要退出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 中测试了上述示例;它可以工作,但(根据我的问题)不打印任何值)

谢谢!

4

3 回答 3

3

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

编辑 1: 仅仅因为您使用 LineEnd 获得无限循环并不意味着 Literal('\n') 更好。尝试.setDebug()在定义的末尾添加_eol,您会发现它永远不会匹配任何内容。

与其尝试将您的评论正文定义为“一个或多行不是结束行,而是将所有内容都写到行尾”,不如这样做:

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

(您使用 LineEnd() 获得无限循环的原因是您本质上是在执行 OneOrMore(SkipTo(LineEnd())),但从不使用 LineEnd(),因此 OneOrMore 只是保持匹配、匹配和匹配、解析和由于解析位置位于行尾,因此返回一个空字符串。)

于 2011-10-19T19:02:38.847 回答
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']]]
于 2011-10-19T19:51:42.337 回答
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
于 2011-10-19T22:51:10.553 回答