Domanda

Ho scritto una piccola funzione, che utilizza ElementTree e XPath per estrarre il contenuto del testo di alcuni elementi in un file XML:

#!/usr/bin/env python2.5

import doctest
from xml.etree import ElementTree
from StringIO import StringIO

def parse_xml_etree(sin, xpath):
  """
Takes as input a stream containing XML and an XPath expression.
Applies the XPath expression to the XML and returns a generator
yielding the text contents of each element returned.

>>> parse_xml_etree(
...   StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
...   '//elem1').next()
'one'
>>> parse_xml_etree(
...   StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
...   '//elem2').next()
'two'
>>> parse_xml_etree(
...   StringIO('<test><null>&#0;</null><elem3>three</elem3></test>'),
...   '//elem2').next()
'three'
"""

  tree = ElementTree.parse(sin)
  for element in tree.findall(xpath):
    yield element.text  

if __name__ == '__main__':
  doctest.testmod(verbose=True)

La terza prova non riesce con il seguente eccezione:

ExpatError: riferimento al numero di carattere non valido: riga 1, colonna 13

è l'entità &#0; XML illegale? Indipendentemente se si tratta o no, i file che voglio analizzare lo contengono, e ho bisogno di un modo per analizzare loro. Eventuali suggerimenti per un altro parser di Expat, o le impostazioni per Expat, che mi avrebbe permesso di farlo?


Aggiornamento: Ho scoperto BeautifulSoup solo ora, un parser tag zuppa come indicato di seguito nel risposta commento, e per divertimento sono andato di nuovo a questo problema e ha cercato di usarlo come un XML-pulitore di fronte elementtree, ma doverosamente ha convertito il &#0; in un just-in-validi nulla di byte. : -)

cleaned_s = StringIO(
  BeautifulStoneSoup('<test><null>&#0;</null><elem3>three</elem3></test>',
                     convertEntities=BeautifulStoneSoup.XML_ENTITIES
  ).renderContents()
)
tree = ElementTree.parse(cleaned_s)

... rendimenti

xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 12

Nel mio caso particolare, però, non ho davvero bisogno il parsing XPath come tale, ho potuto andare con BeautifulSoup se stessa e il suo nodo abbastanza semplice rivolgendosi parsed_tree.test.elem1.contents[0] stile.

È stato utile?

Soluzione

&#0; non è nella gamma carattere legale definito dalle specifiche XML . Ahimè, le mie capacità Python sono piuttosto rudimentali, quindi non sono molto aiuto lì.

Altri suggerimenti

&#0; non è un carattere XML valido. Idealmente, si sarebbe in grado di ottenere il creatore del file per cambiare il loro processo in modo che il file non era valido come questo.

Se è necessario accettare questi file, si potrebbe loro pre-trattamento per trasformare &#0 in qualcos'altro. Ad esempio, selezionare @ come carattere di escape, girare "@" in "@@", e "&#0;" in "@ 0".

Quindi, come si ottiene i dati di testo dal parser, è possibile invertire la mappatura. Questo è solo un esempio, si può inventare qualsiasi sintassi fuggire ti piace.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top