Questo è notevolmente facile con lxml *, utilizzando i parse()
e tostring()
funzioni:
from lxml.etree import parse, tostring
In primo luogo si analizza il documento e ottenere il vostro elemento (sto usando XPath, ma è possibile utilizzare quello che vuoi):
doc = parse('test.xml')
element = doc.xpath('//text')[0]
La funzione tostring()
restituisce una rappresentazione testuale del vostro elemento:
>>> tostring(element)
'<text>Some <text>text</text> with <extradata>data</extradata> in it.</text>\n'
Tuttavia, non si desidera che gli elementi esterni, in modo che possiamo rimuovere con un semplice str.replace()
chiamata:
>>> tostring(element).replace('<%s>'%element.tag, '', 1)
'Some <text>text</text> with <extradata>data</extradata> in it.</text>\n'
noti che str.replace()
ricevuto 1 come terzo parametro, in modo che rimuoverà solo la prima occorrenza del tag di apertura. Si può fare anche con il tag di chiusura.Ora, invece di 1, si passa da -1 a sostituire:
>>> tostring(element).replace('</%s>'%element.tag, '', -1)
'<text>Some <text>text with <extradata>data</extradata> in it.\n'
La soluzione, naturalmente, è quello di fare tutto in una volta:
>>> tostring(element).replace('<%s>'%element.tag, '', 1).replace('</%s>'%element.tag, '', -1)
'Some <text>text with <extradata>data</extradata> in it.\n'
EDIT: @Charles fatto un buon punto : questo codice è fragile poiché il tag può avere attributi. Una possibile soluzione ma ancora limitata è quello di dividere la stringa al primo >
:
>>> tostring(element).split('>', 1)
['<text',
'Some <text>text</text> with <extradata>data</extradata> in it.</text>\n']
ottenere la seconda stringa risultante:
>>> tostring(element).split('>', 1)[1]
'Some <text>text</text> with <extradata>data</extradata> in it.</text>\n'
poi rsplitting esso:
>>> tostring(element).split('>', 1)[1].rsplit('</', 1)
['Some <text>text</text> with <extradata>data</extradata> in it.', 'text>\n']
e arrivare finalmente il primo risultato:
>>> tostring(element).split('>', 1)[1].rsplit('</', 1)[0]
'Some <text>text</text> with <extradata>data</extradata> in it.'
Tuttavia, questo codice è ancora fragile, dal momento che >
è un carattere perfettamente valido in XML, anche all'interno degli attributi.
In ogni caso, devo riconoscere che MattH solution è la vera soluzione generale.
* In realtà questa soluzione funziona anche con ElementTree, il che è ottimo se non si vuole dipendere da lxml. L'unica differenza è che non avrai modo di usare XPath.
L'OP vuole ottenere il contenuto di un elemento specifico. La tua soluzione non funziona in questo caso, almeno non direttamente. Ho ottenuto un elemento con 'e = t.xpath ('// text') [0]' e provato (''' .join (map (etree.tostring, e))') ma il risultato era '' dati in esso.''. –
brandizzi
@brandizzi Buon punto. Aggiornato per riflettere questo. – Marcin
È necessario testare su alcuni altri casi, ma il tuo ultimo esempio funziona bene per me (finora). Quando si usa 'find' invece di' xpath' funziona anche con lo standard '' etree''. – Brutus