我的任务是解析Plone ZODB的巨大备份.没有其他方法可以获得备份,但是在一个大约433mb大的XML文件中.
请不要问为什么或如何,我只是解析文件的任务,以检索图片,文件和其他重要数据.
我已经用Java编写了一个基于StAX的XML解析器,它现在可以读取文件,存储信息并在必要时将其打印到txt文件中.
现在我的问题是:我需要检索的数据在哪里.据我所知,XML文件(即使是16GB内存也很难),它的节点都是一样的,只有属性与另一个不同(即记录节点中的"id"和"aka")其中有超过40000]).
是否有任何Plone或ZODB Dev可以帮助并指出我在这样的XML文件中存储数据的方式和位置的方向?我需要将哪种数据提供给解析器才能查找,存储和打印信息.
或者是否有任何关于如何从XML文件中检索数据的想法?
请记住,我>>不能"以此Plone.xml为基础使用其他任何东西.出于隐私和安全的明显原因,我也无法共享该文件.
XML格式表示ZODB对象条目.
ZODB使用该pickle模块作为将对象序列化为字节序列的基础.XML文件格式试图为Python原始类型(数字,字符串,容器)提供单独的XML标记,但您仍然可以获得"原始"对象数据,这些数据可能包含许多可能不是那么有趣的条目.你的任务.
在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>
Run Code Online (Sandbox Code Playgroud)
然后,这表示具有两个值的Python元组; base64编码的持久ID(记录引用)和Python对象引用; 后者可以被忽略,因为相同的信息在引用的<record>元素中被编码.
的永久ID值是指另一个记录; 解除引用这些的最简单方法是将它与标记的aka属性相匹配<record>:
<record id="[persistentid]" aka="[base64-encoded-persistentid]">
Run Code Online (Sandbox Code Playgroud)
的永久ID是一个真正的无符号长整数的8字节大端表示; 该id属性表示相同的数字:
>>> import struct
>>> 'AAAAAAAAAGU='.decode('base64')
'\x00\x00\x00\x00\x00\x00\x00e'
>>> struct.unpack('>Q', 'AAAAAAAAAGU='.decode('base64'))
(101,)
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
用于状态的类型取决于pickle对象的特定类; 默认是获取类__dict__并对其进行编码,但特定实现可以选择实现自定义__getstate__方法(和相应的__setstate__).BTrees例如,对于包,您通常会找到键值对和 Bucket对象,它们只是将较大的btree分解为单独的记录.
任何未从特殊持久性类继承的类的实例(因此不会获得单独的记录)都存储为<object>标记,其中Python类记录为<klass>标记,后跟初始对象参数的元组,以及可选状态.
如果您正在寻找大型二进制内容(图像,文件),您可能会运气不佳,因为所有现代Plone版本都使用ZODB BLOB支持,其中此类数据存储在单独的文件中.XML文件仅指向空的持久性记录,然后通过其他方式找到ZODB blob内容:
<record id="11545" aka="AAAAAAAALRk=">
<pickle>
<global id="11545.1" name="Blob" module="ZODB.blob"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
Run Code Online (Sandbox Code Playgroud)
该<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>
Run Code Online (Sandbox Code Playgroud)
这里_dt_reconstructor用来创建一个新的副本Products.CMFPlone.UnicodeSplitter.splitter.Splitter; 它没有其他状态(没有<state>标签).
| 归档时间: |
|
| 查看次数: |
181 次 |
| 最近记录: |