<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><style>p {margin:0px;padding:0px;} blockquote { border: 0px; margin-top: 0px; margin-bottom: 0px; }</style></head><body style="">
<p>Hi,</p><p>&nbsp;</p><p><font color="#000000" face="Verdana" size="2"><blockquote type="cite"><br>Here is the result:<br><br>$ python ./try_objectify.py<br>site = None [ObjectifiedElement]<br>  * xsi:type = 'site'<br>    title = Achille 2.0 [MyString]<br>      * xsi:type = 'title'<br>    value = 2L [LongElement]<br>      * xsi:type = 'long'<br><br>So I managed to get some success, but here are some remaining questions.<br><br>- Why is the root element still an ObjectifiedElement instance ? It<br>seems to me I applied the same rules for both of my defined types.</blockquote></font></p><p>&nbsp;<br><font color="#000000" face="Verdana" size="2">Basically, when lxml parses an XML file/string, the underlying libxml2 is used</font></p><p><font color="#000000" face="Verdana" size="2">to build a DOM-like XML-Tree, i.e. a C data structure. On element access,</font></p><p><font color="#000000" face="Verdana" size="2">lxml creates a&nbsp; proxy object to represent the&nbsp; node in Python.&nbsp; After&nbsp; you´ve</font></p><p><font color="#000000" face="Verdana" size="2">finished your proceedings with the&nbsp; node&nbsp; and delete your Python references</font></p><p><font color="#000000" face="Verdana" size="2">to it, it is free to be garbage-collected.</font></p><p>&nbsp;</p><p><font color="#000000" face="Verdana" size="2">Now, objectify bases&nbsp;its element class lookup (i.e. which element class to</font></p><p><font color="#000000" face="Verdana" size="2">use for the Python proxy representation) on certain rules:</font></p><p>&nbsp;</p><p>1. if element has children =&gt; no data class<br>2. if element is defined as xsi:nil, return NoneElement class<br>3. check for Python type hint<br>4. check for XML Schema type hint<br>5. guess element class</p><p>&nbsp;</p><p>Therefore, the objectify class lookup will *always* choose ObjectifiedElement if an</p><p>element has children ("structural element"), as opposed to a "data element".</p><p>&nbsp;</p><p>You can beat this behaviour by using custom element class lookup (with <font><font color="#000000" face="Verdana" size="2">ObjectifyElementClassLookup </font></font></p><p><font><font color="#000000" face="Verdana" size="2"></font></font>as the fallback) based on attributes:</p><p>&nbsp;</p><p>$ cat lxml_attributeBasedLookup.py<br>from lxml import etree, objectify<br>&nbsp;<br>&nbsp;<br>class Configuration(objectify.ObjectifiedElement):<br>&nbsp;&nbsp;&nbsp; pass<br>&nbsp;<br>class MyString(objectify.ObjectifiedDataElement):<br>&nbsp;&nbsp;&nbsp; pass<br>&nbsp;<br>&nbsp;<br># maps attribute values to element classes<br>xsitype_class_mapping = {<br>&nbsp;&nbsp;&nbsp; "site": Configuration,<br>&nbsp;&nbsp;&nbsp; "title": MyString,<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>lookup = etree.AttributeBasedElementClassLookup(<br>&nbsp;&nbsp;&nbsp; "{http://www.w3.org/2001/XMLSchema-instance}type",<br>&nbsp;&nbsp;&nbsp; xsitype_class_mapping,<br>&nbsp;&nbsp;&nbsp; objectify.ObjectifyElementClassLookup())<br>&nbsp;<br>parser = etree.XMLParser()<br>parser.setElementClassLookup(lookup)<br>objectify.setDefaultParser(parser)<br>&nbsp;<br>root = objectify.fromstring("""<br>&lt;site xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xsi:type='site'&gt;<br>&nbsp;<br>&nbsp; &lt;title xsi:type='title'&gt;Achille 2.0&lt;/title&gt;<br>&nbsp; &lt;value xsi:type='long'&gt;2&lt;/value&gt;<br>&lt;/site&gt;<br>""")<br>&nbsp;<br>print objectify.dump(root)&nbsp;</p><p></p>######################<p>&nbsp;</p><p>&nbsp;</p><p>$&nbsp;python2.4 lxml_attributeBasedLookup.py<br>site = None [Configuration]<br>&nbsp; * xsi:type = 'site'<br>&nbsp;&nbsp;&nbsp; title = Achille 2.0 [MyString]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * xsi:type = 'title'<br>&nbsp;&nbsp;&nbsp; value = 2L [LongElement]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * xsi:type = 'long'&nbsp;</p><br><p><font color="#000000" face="Verdana" size="2"></font><font color="#000000" face="Verdana" size="2"><blockquote type="cite">- Is there a way to specify the xsi:type in a schema sheet ? This<br>question may sound stupid, but I'm still learning the XSD spec, and I<br>wonder if objectify could rely entirely on the schema, without the need<br>to add anything in the XML document itself.</blockquote></font></p><p>&nbsp;</p><p><font color="#000000" face="Verdana" size="2">You can define custom types in XML Schema, probably the best is to look at the </font></p><p><font color="#000000" face="Verdana" size="2">XML Schema Primer first, or the excellent tutorials of a certain Roger Costello</font></p><p><font color="#000000" face="Verdana" size="2">(I think the site is xfront.com)</font></p><p>&nbsp;</p><p><font color="#000000" face="Verdana" size="2">Currently, I think lxml.objectify</font> restricts itself to supporting the "xsd" types as in</p><p>http://www.w3.org/TR/xmlschema-2/ with regard to xsi:type values, e.g. forcing</p><p>them to come from the schema namespace.&nbsp;</p><p>&nbsp;</p><p>You might be able to achieve what you need with what I've shown above, beating</p><p>the objectify lookup in lookup order.</p><p>&nbsp;</p><p>For now, there is nothing like a "typifier" that takes an instance and a schema</p><p>and adds type information from the schema to the instance document.</p><p>&nbsp;</p><p>Cheers,</p><p>Holger&nbsp;</p><p></p><p></p><p></p><p><font><font></font></font></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><div class="signature"><br /><br /><br />-- <br />Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen! <br />Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer</div></body></html>