使用PyXB,我想序列化一个子节点,然后能够将其解析回来。这种朴素的方式是行不通的,因为根据模式,子节点不是有效的根元素。
我的方案:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root" type="Root"/>
<xsd:complexType name="Root">
<xsd:sequence>
<xsd:element name="item" maxOccurs="unbounded" type="Item"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Item">
<xsd:sequence>
<xsd:element name="val"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>和示例XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<item>
<val>1</val>
</item>
<item>
<val>2</val>
</item>
<item>
<val>3</val>
</item>
</root>我需要能够序列化一个特定的项目,然后加载它回来。如下所示:
>>> root = CreateFromDocument(sample)
# locate a sub node to serialize
>>> root.item[1].toxml()
'<?xml version="1.0" ?><item><val>2</val></item>'
# load the sub node, getting an Item back
>>> sub_node = CreateFromDocument('<?xml version="1.0" ?><item><val>2</val></item>')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "binding.py", line 63, in CreateFromDocument
instance = handler.rootObject()
File "pyxb/binding/saxer.py", line 285, in rootObject
raise pyxb.UnrecognizedDOMRootNodeError(self.__rootObject)
pyxb.exceptions_.UnrecognizedDOMRootNodeError: <pyxb.utils.saxdom.Element object at 0x7f30ba4ac550>
# or, perhaps, some kind of unique identifier:
>>> root.item[1].hypothetical_unique_identifier()
'//root/item/1'
>>> sub_node = CreateFromDocument(sample).find_node('//root/item/1')
<binding.Item object at 0x7f30ba4a5d50>这当然不起作用,因为根据模式,item不能是根节点。有没有办法只解析一个子树,取而代之的是一个项目呢?
或者,有没有什么方法可以唯一地标识一个子节点,以便我以后可以找到它?
发布于 2015-10-10 04:18:44
PyXB不能解析以非全局元素开头的文档,因为非全局元素的验证自动机状态不是开始状态。
虽然我最初想支持像XPath这样的东西,但它从来没有实现过,也没有标准的唯一标识符来携带结构信息。如果您需要标记一个成员元素,以便将其删除,然后将其放回原来的位置,则只需将附加属性分配给对象并在应用程序级别使用它们即可;例如:
e = root.item[1]
e.__mytag = '//root/item/1'然后,您可以编写一个遍历对象树以查找匹配项的函数。当然,这样的属性将仅与该实例相关联,因此随后将不同的对象分配给root.item[1]不会自动继承相同的属性。
发布于 2015-10-10 04:55:02
我最终做到这一点的方法是使用元素的起始行和列号来标识它。
我将这个混入添加到我的所有元素中:
class IdentifierMixin(object):
"""
Adds an identifier property unique to this node that can be used to locate
it in the document later.
"""
@property
def identifier(self):
return '%s-%s' % (self._location().lineNumber, self._location().columnNumber)然后使用此函数查找节点:
def find_by_identifier(root, identifier):
# BFS over the tree because usually the identifier we're looking for will
# be close to the root.
stack = collections.deque([root])
while stack:
node = stack.popleft()
if node.identifier == identifier:
return node
stack.extend(node.content())https://stackoverflow.com/questions/33024394
复制相似问题