Хруст XML с Python - PullRequest
       17

Хруст XML с Python

5 голосов
/ 20 марта 2009

Мне нужно удалить пробелы между тегами xml, например если оригинальный XML выглядит так:

<node1>
    <node2>
        <node3>foo</node3>
    </node2>
</node1>

Я бы хотел, чтобы конечный результат был сжатым до одной строки:

<node1><node2><node3>foo</node3></node2></node1>

Обратите внимание, что я не буду контролировать структуру xml, поэтому решение должно быть достаточно универсальным, чтобы можно было обрабатывать любой действительный xml. Также xml может содержать блоки CDATA, которые мне нужно исключить из этого хруста и оставить их как есть.

Пока у меня есть пара идей: (1) проанализировать xml как текст и найти начало и конец тегов <и> (2) другой подход - это загрузить документ xml и перейти от узла к узлу и напечатать новый документ путем объединения тегов.

Я думаю, что любой из методов сработает, но я бы не стал изобретать колесо здесь, так что, может быть, есть библиотека Python, которая уже делает что-то подобное? Если нет, то о каких проблемах / подводных камнях нужно знать, когда выкатываете мой собственный cruncher ? Любые рекомендации?

EDIT Спасибо всем за ответы / предложения, решения Триптиха и Ван Гейла работают для меня и делают именно то, что я хочу. Хотел бы я принять оба ответа.

Ответы [ 4 ]

8 голосов
/ 20 марта 2009

Это довольно легко сделать с помощью lxml (примечание: эта особенность отсутствует в ElementTree):

from lxml import etree

parser = etree.XMLParser(remove_blank_text=True)

foo = """<node1>
    <node2>
        <node3>foo  </node3>
    </node2>
</node1>"""

bar = etree.XML(foo, parser)
print etree.tostring(bar,pretty_print=False,with_tail=True)

Результат:

<node1><node2><node3>foo  </node3></node2></node1>

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

parser = etree.XMLParser(remove_blank_text=True, strip_cdata=False)
5 голосов
/ 20 марта 2009

Я бы использовал XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*">
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Это должно сработать.

В Python вы можете использовать lxml (прямая ссылка на образец на домашней странице) для его преобразования.

Для некоторых тестов используйте xsltproc, образец:

xsltproc test.xsl  test.xml

где test.xsl - это файл выше, а test.xml ваш файл XML.

4 голосов
/ 20 марта 2009

Довольно просто с BeautifulSoup.

В этом решении предполагается, что можно удалять пробелы из хвостовых концов символьных данных.
Пример: <foo> bar </foo> становится <foo>bar</foo>

Он будет правильно игнорировать комментарии и CDATA.

import BeautifulSoup

s = """
<node1>
    <node2>
        <node3>foo</node3>
    </node2>
    <node3>
      <!-- I'm a comment! Leave me be! -->
    </node3>
    <node4>
    <![CDATA[
      I'm CDATA!  Changing me would be bad!
    ]]>
    </node4>
</node1>
"""

soup = BeautifulSoup.BeautifulStoneSoup(s)

for t in soup.findAll(text=True):
   if type(t) is BeautifulSoup.NavigableString: # Ignores comments and CDATA
      t.replaceWith(t.strip())

print soup
2 голосов
/ 20 марта 2009

На самом деле не решение, но так как вы попросили рекомендации: я бы не советовал делать собственный анализ (если вы не хотите научиться писать сложный синтаксический анализатор), потому что, как вы говорите, не все пробелы должны быть удалены. Существуют не только блоки CDATA, но также и элементы с атрибутом «xml: space = preserve», которые соответствуют вещам типа <pre> в XHTML (где вложенные пробелы фактически имеют значение), и пишут анализатор, способный распознавать эти элементы и оставить пробелы в покое было бы возможно, но неприятно.

Я бы использовал метод синтаксического анализа, то есть загрузил документ и пошел бы распечатывать их по узлам. Таким образом, вы можете легко определить, из каких узлов вы можете убрать пробелы, а какие нет. В стандартной библиотеке Python есть несколько модулей, ни один из которых я никогда не использовал ;-), которые могут быть вам полезны ... попробуйте xml.dom, или я не уверен, что вы могли бы сделать это с xml.parsers.expat.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...