удалите все между 2 тегами, которые охватывают ответвления дерева XML

Я пытаюсь удалить все в XML-документе между 2 тегами, с помощью Python и lxml., которым проблема состоит в том, что теги могут быть в различных ответвлениях дерева (но всегда на той же глубине), документ в качестве примера мог бы быть похожим на это.

<root>
    <p> Hello world <start />this is a paragraph </p>
    <p> Goodbye world. <end />I'm leaving now </p>
</root>

я хотел бы удалить все между запуском и конечными тэгами. который привел бы к единственному тегу p:

<root>
    <p> Hello world I'm leaving now </p>
</root>

у кого-либо есть какая-либо идея, как это могло бы быть выполнено с помощью lxml и Python?

1
задан user61000 4 August 2010 в 01:20
поделиться

3 ответа

Вы можете попробовать использовать SAX-подобный целевой интерфейс парсера :

from lxml import etree

class SkipStartEndTarget:
    def __init__(self, *args, **kwargs):
        self.builder = etree.TreeBuilder()
        self.skip = False

    def start(self, tag, attrib, nsmap=None):
        if tag == 'start':
            self.skip = True
        if not self.skip:
            self.builder.start(tag, attrib, nsmap)

    def data(self, data):
        if not self.skip:
            self.builder.data(data)

    def comment(self, comment):
        if not self.skip:
            self.builder.comment(self)

    def pi(self, target, data):
        if not self.skip:
            self.builder.pi(target, data)

    def end(self, tag):
        if not self.skip:
            self.builder.end(tag)
        if tag == 'end':
            self.skip = False

    def close(self):
        self.skip = False
        return self.builder.close()

Затем вы можете использовать класс SkipStartEndTarget , чтобы создать цель парсера , и создайте собственный XMLParser с этой целью, например:

parser = etree.XMLParser(target=SkipStartEndTarget())

Вы по-прежнему можете предоставить синтаксическому анализатору другие параметры, если они вам нужны. Затем вы можете предоставить этот синтаксический анализатор функции синтаксического анализатора, который вы используете, например:

elem = etree.fromstring(xml_str, parser=parser)

Это также работает с etree.XML () и etree.parse () , и вы может даже установить синтаксический анализатор как синтаксический анализатор по умолчанию с помощью etree.setdefaultparser () (что, вероятно, не является хорошей идеей). Одна вещь, которая может вас сбить с толку: даже с etree.parse () , это не вернет дерево элементов, но всегда будет элемент (как etree.XML () и etree .fromstring () делать). Я не думаю, что это можно сделать (пока), поэтому, если это проблема для вас, вам придется как-то ее обойти.

Обратите внимание, что также можно использовать создание дерева элементов из событий sax с помощью lxml.sax , что, вероятно, несколько сложнее и медленнее. В отличие от приведенного выше примера, он вернет дерево элементов, но я думаю, что он не предоставляет .docinfo , которое вы получили бы при обычном использовании etree.parse () . Я также считаю, что он (в настоящее время) не поддерживает комментарии и пи.(еще не использовал его, поэтому на данный момент я не могу быть более точным)

Также обратите внимание, что любой подход к синтаксическому анализу документа, подобный SAX, требует пропуска всего между и по-прежнему будет приводить к правильно сформированному документу, как в вашем примере, но не было бы так, если бы второй

был , например, так как вы получите

.... .

0
ответ дан 2 September 2019 в 22:28
поделиться

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

import re
new_string = re.sub(r'<start />(.*?)<end />', '', your_string, re.S)

Вы не можете использовать синтаксический анализатор XML, если это недопустимый XML.

1
ответ дан 2 September 2019 в 22:28
поделиться

У вас беспорядок в руках, и вам следует ударить человека, который написал преднамеренное искажение правила вложенности XML.

Вам, вероятно, лучше всего использовать что-то вроде SAX , чтобы распознать тег и начать отбрасывать ввод, пока вы не нажмете . SAX имеет здесь преимущество перед lxml, потому что он позволяет вам выполнять произвольные действия для каждой лексемы, в то время как lxml уже разделит начало и конец, прежде чем вы дойдете до них.

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

1
ответ дан 2 September 2019 в 22:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: