Синтаксический анализ Python LXML с вложенными элементами

#python #xml #lxml

#python #xml #lxml

Вопрос:

Я хотел бы получить содержимое определенного элемента в XML-файле. Однако внутри XML-элемента есть другие XML-элементы, которые препятствуют правильному извлечению содержимого из родительского тега. Пример:

 xml = '''<?xml version='1.0' ?><test><claim-text><b>2</b>. A protective uniform for use by a person in combat or law enforcement, said uniform comprising: <claim-text>a. an upper body garment and a separate lower body garment</claim-text> <claim-text>b. a plurality of a ballistic and non-ballistic panels for attaching to the upper body garment and the lower body garment, and;</claim-text></claim-text></test>'''

context = etree.iterparse(StringIO(xml), events=('end',), tag='claim-text')
for event, element in context:
  print element.text
  

что приводит к:

 a. an upper body garment and a separate lower body garment
b. a plurality of a ballistic and non-ballistic panels for attaching to the upper body garment and the lower body garment, and;
None
  

Однако, например, ‘защитная форма для использования ..’ пропущен. Кажется, что каждым элементом ‘claim-text’, который имеет другие внутренние элементы, пренебрегают. Как я должен изменить синтаксический анализ XML, чтобы получить все утверждения?

Спасибо

Я только что решил это с помощью «обычного» подхода синтаксического анализатора SAX:

 class SimpleXMLHandler(object):

  def __init__(self):
    self.buffer = ''
    self.claim = 0

  def start(self, tag, attributes):
    if tag == 'claim-text':
      if self.claim == 0:
        self.buffer = ''
      self.claim = 1

  def data(self, data):
    if self.claim == 1:
      self.buffer  = data

  def end(self, tag):
    if tag == 'claim-text':
      print self.buffer
      self.claim = 0

  def close(self):
    pass
  

Ответ №1:

Вы могли бы использовать xpath для поиска и объединения всех текстовых узлов непосредственно под каждым <claim-text> узлом, вот так:

 from StringIO import StringIO
from lxml import etree
xml = '''<?xml version='1.0' ?><test><claim-text><b>2</b>. A protective uniform for use by a person in combat or law enforcement, said uniform comprising: <claim-text>a. an upper body garment and a separate lower body garment</claim-text> <claim-text>b. a plurality of a ballistic and non-ballistic panels for attaching to the upper body garment and the lower body garment, and;</claim-text></claim-text></test>'''

context = etree.iterparse(StringIO(xml), events=('start',), tag='claim-text')
for event, element in context:
  print ''.join(element.xpath('text()'))
  

который выводит:

 . A protective uniform for use by a person in combat or law enforcement, said uniform comprising:  
a. an upper body garment and a separate lower body garment
b. a plurality of a ballistic and non-ballistic panels for attaching to the upper body garment and the lower body garment, and;