Формат XML представляет записи объектов ZODB.
ZODB использует модуль pickle
в качестве основы для сериализации объектов в последовательность байтов. . Формат файла XML пытается дать вам отдельные теги XML для примитивных типов Python (числа, строки, контейнеры), но вы все равно получаете «сырые» данные объекта, которые могут содержать множество записей, которые, вероятно, не так уж интересны для пользователя. твое задание.
В ZODB хранится целое дерево объектов; объекты, содержащие другие объекты, содержащие еще больше. Чтобы предотвратить любые изменения в этом дереве, требующие полной перезаписи сохраненных данных, объекты могут наследовать от выделенного класса сохраняемости, который отдельно отслеживает изменения только этого объекта, а записи затем используют ссылки на эти отдельные записи.
Затем формат XML содержит на верхнем уровне <record>
элементов; они представляют собой отдельные объекты с атрибутами в дереве, и если они содержат другие постоянные объекты, ссылки между ними кодируются как элементы <persistent>
; выглядит примерно так:
<persistent>
<tuple>
<string id="[persistentid.subid]" encoding="base64">[base64-encoded-persistentid]</string>
<global id="[persistentid.subid]" name="[classname]" module="[module for class]"/>
</tuple>
</persistent>
Затем он представляет собой кортеж Python с двумя значениями; постоянный идентификатор в кодировке base64 (ссылка на запись) и ссылка на объект Python; последний может быть проигнорирован, так как та же самая информация закодирована в указанном элементе <record>
.
Значение постоянный идентификатор относится к другой записи; самый простой способ разыменовать их — сопоставить их с атрибутом aka
тега <record>
:
<record id="[persistentid]" aka="[base64-encoded-persistentid]">
постоянный идентификатор на самом деле представляет собой 8-байтовое представление длинного целого числа без знака с обратным порядком байтов; атрибут id
представляет тот же номер:
>>> import struct
>>> 'AAAAAAAAAGU='.decode('base64')
'\x00\x00\x00\x00\x00\x00\x00e'
>>> struct.unpack('>Q', 'AAAAAAAAAGU='.decode('base64'))
(101,)
Каждый тег <record>
содержит 1 или 2 тега <pickle>
; первый кодирует тип объекта, второй, если он присутствует, состояние объекта. Без второй записи объект просто пуст:
<record id="[persistentid]" aka="[base64-encoded-persistentid]">
<pickle>
<global id="[persistentid].1" name="[classname]" module="[module for class]"/>
</pickle>
<pickle>
<!-- ... -->
</pickle>
</record>
Какой тип используется для состояния, зависит от конкретного класса маринованного объекта; по умолчанию берется класс __dict__
и кодируется, но в некоторых реализациях можно реализовать пользовательский метод __getstate__
(и соответствующий __setstate__
). Например, для пакета BTrees
вы обычно найдете как пары "ключ-значение" , так и объекты Bucket
, которые нужны только для того, чтобы разбить большое b-дерево на отдельные записи.
Любые экземпляры классов, которые не наследуются от специального класса постоянства (и, следовательно, не получают отдельной записи), хранятся как теги <object>
с классом Python, записанным как тег <klass>
, за которым следует кортеж для начальных аргументов объекта, плюс необязательное состояние.
Если вы ищете большой двоичный контент (изображения, файлы), вам может не повезло, так как все современные версии Plone используют поддержку ZODB BLOB, где такие данные хранятся в отдельных файлах. Файл XML будет просто указывать на пустые постоянные записи, в которых содержимое больших двоичных объектов ZODB затем можно найти другими способами:
<record id="11545" aka="AAAAAAAALRk=">
<pickle>
<global id="11545.1" name="Blob" module="ZODB.blob"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
Тег <none/>
представляет объект Python None
(эквивалентен null
в Java). После этого данные BLOB-объектов не включаются в экспорт.
Другие случайные заметки:
теги <reference>
представляют собой ссылку на уже закодированный ранее объект, а не тот, который имеет отдельный постоянный <record>
; они указывают на [persistentid.subid]
значений. В конце концов, нет смысла записывать один и тот же объект более одного раза.
Значения тега <unicode>
закодированы с помощью UTF-8; атрибут encoding
никогда не будет установлен.
Модуль DateTime.DateTime
зарегистрировал оболочку для внутренней copy_reg
функции модуля, используемой для обработки расширения. виды; вы, вероятно, найдете записи следующего содержания:
<object id="5406.12">
<klass>
<global id="5406.9" name="_dt_reconstructor" module="DateTime.DateTime"/>
</klass>
<tuple>
<global id="5406.10" name="Splitter" module="Products.CMFPlone.UnicodeSplitter.splitter"/>
<global id="5406.11" name="object" module="__builtin__"/>
<none/>
</tuple>
</object>
Здесь _dt_reconstructor
вместо этого используется для создания новой копии Products.CMFPlone.UnicodeSplitter.splitter.Splitter
; у него нет другого состояния (нет тега <state>
).
person
Martijn Pieters
schedule
11.08.2014
<?xml version="1.0"?> <ZopeData> <record id="" aka=""> <pickle> <global id="" name="" module=""/> </pickle> <pickle> <dictionary id=""> <item> <key><string id="" encoding=""></string></key> <value> <list id=""> <string id="" encoding=""></string> <string id="" encoding=""></string> <string id="" encoding=""></string> <string id="" encoding=""></string> . . .
- person HellsBell   schedule 10.08.2014