Лучший способ преобразовать пользовательский XML как синтаксис - PullRequest
5 голосов
/ 15 июля 2011

Использование Python.

Так что в основном у меня есть синтаксис тегов типа XML, но у тегов нет атрибутов.Так что <a>, но не <a value='t'>.Они регулярно закрываются с </a>.

Вот мой вопрос.У меня есть нечто, похожее на это:

<al>
1. test
2. test2
 test with new line
3.  test3
<al>
    1. test 4
    <al>
        2. test 5
        3. test 6
        4. test 7
    </al>
</al>
4. test 8
</al>

И я хочу преобразовать это в:

<al>
<li>test</li>
<li> test2</li>
<li> test with new line</li>
<li>  test3
<al>
    <li> test 4 </li>
    <al>
        <li> test 5</li>
        <li> test 6</li>
        <li> test 7</li>
    </al>
    </li>
</al>
</li>
<li> test 8</li>
</al>

Я на самом деле не ищу законченное решение, а скорее толчок вправильное направление.Мне просто интересно, как люди здесь подойдут к проблеме.Исключительно РЕГЕКС?написать полный собственный синтаксический анализатор для синтаксиса тега без атрибутов?Взломать существующие парсеры XML?и т.д.

Заранее спасибо

Ответы [ 4 ]

2 голосов
/ 16 июля 2011

Как вы описали свой синтаксис, это «XML без атрибутов». Если это так, то это все еще XML, так что вы можете использовать инструменты XML, такие как XSLT и XQuery.

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

2 голосов
/ 15 июля 2011

Я бы рекомендовал начать со следующего:

from xml.dom.minidom import parse, parseString

xml = parse(...)
l = xml.getElementsByTagName('al')

затем обходит все элементы в l, проверяя их текстовые подузлы (а также рекурсивно <al> узлы).

Вы можете начать играть с этим прямо сейчас в консоли Python.

Легко удалить текстовые узлы, затем разделить фрагменты текста с помощью chunk.split('\n') и добавить <li> узлов назад, как вам нужно.

После изменения всех узлов <al> вы можете просто позвонить xml.toxml(), чтобы получить полученный xml в виде текста.

Обратите внимание, что объекты элементов, которые вы получаете от этого, связаны с исходным объектом документа xml, поэтому не удаляйте объект xml в процессе.

Таким образом, я лично считаю более простым и легким для отладки, чем манипулирование с многострочными регулярными выражениями.

1 голос
/ 16 июля 2011

Это будет зависеть от того, что именно вы хотите с ним делать, если это один из сценариев, достаточно следующего:

cat in.txt | perl -pe 'if(!/<\/?al>/){s#^(\s*)([0-9]+\.)?(.*)$#$1<li>$3</li>#}'

И это работает.Но я бы не сказал, что это очень надежно;) Но если это разовое, то все в порядке.

0 голосов
/ 16 июля 2011

Мне просто интересно, как люди здесь подойдут к этой проблеме.

Я бы хотел использовать парсер.

Я считаю, что операция, которую вы пытаетесь выполнить, - это не просто синтаксическая или лексическая замена . Это гораздо больше преобразования грамматика , что подразумевает понимание структуры вашего документа .

В вашем примере вы не просто заключаете каждую строку между <li> и </li>; вы также рекурсивно заключаете некоторые блоки документа, которые занимают несколько строк, если они представляют собой «элемент».

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

Дополнительной причиной использования парсера является "реальное слово" . Regex - это настоящие "грамматические нацисты": сбой в вашей разметке, и они не сработают. С другой стороны, все библиотеки синтаксического анализатора являются «гибкими» (обрабатывают одинаково разные варианты написания, например <a></a> и <a/> или HTML <br> и XHTML <br/>), а некоторые - например, beautifulsoup - даже «прощающий», означающий, что они попытаются угадать (с удивительно высоким уровнем точности), что автор документа хотел закодировать, даже если сам документ не прошел проверку.

Кроме того, решение, основанное на синтаксическом анализаторе, гораздо более поддерживаемо , чем решение на основе регулярных выражений. Небольшое изменение в структуре вашего документа может потребовать радикальных изменений вашего регулярного выражения [которые по своей природе становятся неясными для их самого автора через 72 часа или около того].

Наконец, поскольку вы используете python и , поэтому readability counts, решение, основанное на синтаксическом анализаторе, может потенциально привести к гораздо большему количеству кода на pythonic, чем к очень сложному / длинному / неясному регулярному выражению.

НТН!

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