Pregunta

Necesito analizar un archivo que contenga comentarios XML. Específicamente es el archivo AC# usando el MS /// convención.

De esto tendría que sacar foobar, o /// foobar Sería aceptable también. (Nota: esto todavía no funciona si hace el XML todo en una línea ...)

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

Esto es lo que tengo:

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)

y para salir:

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

Pero no he tenido mucho éxito con el Grammer trabajando en múltiples líneas.

(Nota: probé la muestra anterior en Python 3.2; funciona pero (según mi problema) no imprime ningún valor)

¡Gracias!

¿Fue útil?

Solución

¿Qué tal usar 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']]]

Otros consejos

pienso Literal('\n') es tu problema. No querrás construir un literal con personajes de espacios en blanco (ya que los literales de forma predeterminada se omiten el espacio en blanco antes de tratar de igualar). Intenta usar LineEnd() en cambio.

Editar 1:El hecho de que obtenga un bucle infinito con Lineend no significa que literalmente (' n') sea mejor. Intenta agregar .setDebug() al final de tu _eol Definición, y verás que nunca coincide con nada.

En lugar de tratar de definir el cuerpo de su comentario como "una o más líneas que no son una línea de cierre, pero obtenga todo al final de la línea", ¿qué pasa si solo lo hace?

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

(La razón por la que estaba obteniendo un bucle infinito con Lineend () fue que esencialmente estaba haciendo Oneormore (Skipto (Lineend ())), pero nunca consumiendo Lineend (), por lo que el OneMore solo siguió coincidiendo y coincidía y coincidía, analizó y analizó y analizó y analiza devolver una cadena vacía ya que la posición de análisis fue a el final de la línea.)

Podrías usar un analizador XML para analizar XML. Debería ser fácil extraer líneas de comentarios relevantes:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top