Domanda

Ho bisogno di analizzare un file contenente commenti XML. Nello specifico si tratta di un file C # utilizzando la convenzione /// MS.

Da questo avrei bisogno di tirare fuori foobar, o /// foobar sarebbe accettabile, anche. (Nota - questo non fa ancora del lavoro se si effettua l'xml tutto su una riga ...)

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

Ecco quello che ho:

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)

e per l'output:

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

Ma non ho avuto molto successo con la grammatica di lavoro in tutto multilinea.

(nota - ho provato il campione di cui sopra in Python 3.2; funziona, ma (per il mio problema) non stampa alcun valore)

Grazie!

È stato utile?

Soluzione

Come sull'utilizzo 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']]]

Altri suggerimenti

Credo che Literal('\n') è il tuo problema. Non si vuole costruire un letterale con caratteri di spaziatura (dal letterali di default saltare gli spazi prima di cercare di abbinare). Provate ad usare LineEnd() invece.

Modifica 1: Solo perché si ottiene un ciclo infinito con LineEnd non significa che letterale ( '\ n') è meglio. Prova ad aggiungere .setDebug() sulla fine della vostra definizione _eol, e vedrete che non è mai corrisponde a qualsiasi cosa.

Invece di cercare di definire il corpo del vostro commento come "una o più linee che non sono una linea di chiusura, ma avere tutto fino alla fine-of-line", che cosa se lo farete:

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

(La ragione per cui si stavano diventando un ciclo infinito con LineEnd () era che si erano essenzialmente facendo OneOrMore (skipTo (LineEnd ())), ma mai consumando la LineEnd (), in modo che l'OneOrMore continuava corrispondenza e la congruenza e la congruenza , analisi e restituisce una stringa vuota in quanto la posizione di analisi era a alla fine della riga.)

Si potrebbe utilizzare un parser XML per XML analizzano. Dovrebbe essere facile da estrarre importanti righe di commento:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top