2015-09-16 3 views
7

Я немного смущен некоторыми дизайнерскими решениями в API Python ElementTree - они кажутся произвольными, поэтому я хотел бы получить некоторые разъяснения, чтобы увидеть, имеют ли эти решения некоторую логику их, или если они просто более или менее ad hoc.Python ElementTree: ElementTree vs root Element

Итак, как правило, существует два способа генерации ElementTree - один из потоков источника, например, файла или другого потока ввода-вывода. Это достигается с помощью функции parse() или метода класса ElementTree.parse().

Другой способ - загрузить XML непосредственно из строкового объекта. Это можно сделать с помощью функции fromstring().

Хорошо, отлично. Теперь я бы подумал, что эти функции будут в основном идентичны с точки зрения того, что они возвращают, - разница между ними в основном является источником ввода (один берет файл или объект потока, а другой принимает простую строку). За исключением по какой-то причине функция parse() возвращает объект ElementTree, но функция fromstring() возвращает объект Element. Разница в основном состоит в том, что объект Element является элементом корень элемента дерева XML, тогда как объект ElementTree является своего рода «оберткой» вокруг корневого элемента, который предоставляет некоторые дополнительные функции. Вы всегда можете получить корневой элемент из объекта ElementTree, вызвав getroot().

Тем не менее, я смущен, почему мы имеем это различие. Почему fromstring() возвращает корневой элемент напрямую, но parse() возвращает объект ElementTree? Есть ли какая-то логика этого различия?

+1

Честно говоря, 'ElementTree' API имеет некоторые действительно странные решения в разы, и Это одна из них. – gsnedders

+0

Я работаю с lxml и api - это то же самое. Я тоже хотел бы узнать ответ на эти вопросы. Я стараюсь держать вещи на уровне обертки, но я не знаю, почему. –

+1

ElementTree имеет больше возможностей, чем элемент, в частности 'write()'.Я не говорю, что они не могут быть предоставлены для Element, но они являются основными различиями. 'fromstring()' дает вам только элемент, который эффективно мешает вам изменять и писать дерево. – remram

ответ

0

Я думаю то же самое, что remram в комментариях: parse принимает местоположение файла или файл-объект и сохраняет эту информацию, чтобы он мог предоставить дополнительную полезность, что очень полезно. Если parse не возвратил объект ET, вам нужно будет лучше отслеживать источники и еще что-то, чтобы вручную вернуть их обратно в вспомогательные функции, которые по умолчанию имеют объекты ET. В отличие от файлов, Strings-by definition - не имеют такой же информации, что и у них, поэтому вы не можете создавать для них одни и те же утилиты (в противном случае это может быть метод ET.parsefromstring(), который вернет объект ET).

Я подозреваю, что это также логика метода был назван синтаксического анализа вместо ET.fromfile(): Я бы ожидать того же типа объекта должны быть возвращены из FromFile и fromstring, но может Не скажу, что я ожидал бы такого же от parse (с тех пор, как я начал использовать ET, давно не было возможности проверить это, но это мое чувство).

По вопросу Ремрам, поднятый о размещении методов утилиты на Элементах, поскольку я понимаю документацию, Элементы чрезвычайно единообразны, когда дело доходит до реализации. Люди говорят о «Корневых элементах», но Элемент в корне дерева буквально идентичен всем другим элементам в терминах его атрибутов класса и методов. Насколько я знаю, Elements даже не знает, кто их родитель, что, вероятно, поддержит это единообразие. В противном случае может существовать больше кода для реализации «корневого» элемента (который не имеет родителя) или переполярных подэлементов. Мне кажется, что простота класса Element очень важна в его пользу.Поэтому мне лучше оставить Elements в значительной степени агностиком чего-либо выше (их родителя, файла, из которого они происходят), поэтому не может быть никаких помех относительно 4 элементов с разными выходными файлами в одном и том же дереве (или тому подобное).

Когда дело доходит до реализации модуля внутри кода, мне кажется, что сценарий должен был бы распознавать ввод как файл в какой-то момент, так или иначе (в противном случае он пытался передать файл в fromstring). Таким образом, не должно возникнуть ситуации, при которой вывод разбора должен быть неожиданным, так что ElementTree считается элементом и обрабатывается как таковой (если, конечно, анализ не был реализован без проверки программщиком, чтобы видеть что разбор сделал, что только кажется мне плохой привычкой).

3

Прекрасный ответ приходит от этого старого discussion:

Только для записи: Фредрик [создатель ElementTree] фактически не считают его дизайн «бзик». Он утверждает, что он предназначен для разных случаев использования. В то время как parse() анализирует файл, который обычно содержит полный документ (представленный в ET как объект ElementTree), fromstring() и , в частности, 'literal wrapper' XML() предназначены для синтаксического анализа строк, которые ?) часто содержат только фрагменты XML. С фрагментом вы, , обычно хотите продолжать делать такие вещи, как вставка его в другое дерево , поэтому вам нужен элемент верхнего уровня практически во всех случаях.

И:

Почему не et.parse единственный способ сделать это? Почему XML или fromstring ?

Ну, прецеденты. XML() является псевдонимом для fromstring(), потому что это удобно (и хорошо читаемый) написать

раздел = XML ('A до Z') section.append (пункты)

для XML-литералов в исходном коде. fromstring() есть, потому что, когда вы хотите, чтобы разобрать фрагмент из строки, которые вы получили из любого источника, легко выразить, что с именно этой функцией, как и в

el = fromstring(some_string) 

Если вы хотите, чтобы разобрать документ из файла или файлового объекта, используйте parse(). Три варианта использования - три функции. Четвертое использование случай разборе документа из строки не имеет свою собственную функцию, , потому что это тривиально, чтобы написать

tree = parse(BytesIO(some_byte_string)) 
Смежные вопросы