Вопрос

Мне нужно проанализировать файл, содержащий XML -комментарии. В частности, это файл AC# с использованием MS /// соглашение.

Из этого мне нужно вытащить 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; он работает, но (согласно моей проблеме) не печатает никаких значений)

Спасибо!

Это было полезно?

Решение

Как насчет использования 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']]]

Другие советы

Я думаю Literal('\n') ваша проблема. Вы не хотите строить буквальный с персонажами пробела (поскольку литералы по умолчанию пропустите пробел по пробелу, прежде чем пытаться соответствовать). Попробуйте использовать LineEnd() вместо.

РЕДАКТИРОВАТЬ 1:Тот факт, что вы получаете бесконечную петлю с Lineend, не означает, что буквальный (' n') лучше. Попробуйте добавить .setDebug() в конце вашего _eol Определение, и вы увидите, что оно никогда ничего не соответствует.

Вместо того, чтобы пытаться определить тело вашего комментария как «одну или несколько строк, которые не являются закрывающейся линией, но довести все до конца линии», что, если вы просто сделаете:

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

(Причина, по которой вы получали бесконечный цикл с Lineend (), заключалась в том, что вы, по сути, выполняли OneorMore (Skipto (lineend ())), но никогда не потребляли Lineend (), поэтому OneorMore просто продолжал сопоставлять и сопоставлять, анализировать и анализировать Возвращение пустой строки с момента позиции разбора в конец линии.)

Вы можете использовать анализатор 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top