[Lxml-checkins] r43386 - in lxml/trunk: . doc src/lxml

scoder at codespeak.net scoder at codespeak.net
Mon May 14 22:42:52 CEST 2007


Author: scoder
Date: Mon May 14 22:42:51 2007
New Revision: 43386

Modified:
   lxml/trunk/CHANGES.txt
   lxml/trunk/doc/objectify.txt
   lxml/trunk/src/lxml/objectify.pyx
Log:
objectify didn't handle prefixed type names in xsi:type

Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt	(original)
+++ lxml/trunk/CHANGES.txt	Mon May 14 22:42:51 2007
@@ -44,6 +44,8 @@
 Bugs fixed
 ----------
 
+* Objectify couldn't handle prefixed XSD type names in ``xsi:type``
+
 * More ET compatible behaviour when writing out XML declarations or not
 
 * More robust error handling in ``iterparse()``

Modified: lxml/trunk/doc/objectify.txt
==============================================================================
--- lxml/trunk/doc/objectify.txt	(original)
+++ lxml/trunk/doc/objectify.txt	Mon May 14 22:42:51 2007
@@ -733,22 +733,23 @@
 and/or 'xsi:type' information::
 
     >>> root = objectify.fromstring('''\
-    ... <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-    ...   <d xsi:type="double">5</d>
-    ...   <l xsi:type="long"  >5</l>
-    ...   <s xsi:type="string">5</s>
+    ... <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    ...       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+    ...   <d xsi:type="xsd:double">5</d>
+    ...   <l xsi:type="xsd:long"  >5</l>
+    ...   <s xsi:type="xsd:string">5</s>
     ... </root>''')
     >>> objectify.annotate(root)
     >>> print objectify.dump(root)
     root = None [ObjectifiedElement]
         d = 5.0 [FloatElement]
-          * xsi:type = 'double'
+          * xsi:type = 'xsd:double'
           * py:pytype = 'float'
         l = 5L [LongElement]
-          * xsi:type = 'long'
+          * xsi:type = 'xsd:long'
           * py:pytype = 'long'
         s = '5' [StringElement]
-          * xsi:type = 'string'
+          * xsi:type = 'xsd:string'
           * py:pytype = 'str'
     >>> objectify.deannotate(root)
     >>> print objectify.dump(root)
@@ -780,7 +781,7 @@
     root = None [ObjectifiedElement]
         x = 5L [LongElement]
           * py:pytype = 'long'
-          * xsi:type = 'integer'
+          * xsi:type = 'xsd:integer'
 
 There is a side effect of the type lookup.  If you assign a string value using
 attribute assignment and that string value turns out to be valid for any of

Modified: lxml/trunk/src/lxml/objectify.pyx
==============================================================================
--- lxml/trunk/src/lxml/objectify.pyx	(original)
+++ lxml/trunk/src/lxml/objectify.pyx	Mon May 14 22:42:51 2007
@@ -1011,12 +1011,13 @@
     xsi_ns    = "{%s}" % XML_SCHEMA_INSTANCE_NS
     pytype_ns = "{%s}" % PYTYPE_NAMESPACE
     for name, value in cetree.iterattributes(element, 3):
-        if name == PYTYPE_ATTRIBUTE:
-            if value == TREE_PYTYPE:
-                continue
-            else:
-                name = name.replace(pytype_ns, 'py:')
-        name = name.replace(xsi_ns, 'xsi:')
+        if '{' in name:
+            if name == PYTYPE_ATTRIBUTE:
+                if value == TREE_PYTYPE:
+                    continue
+                else:
+                    name = name.replace(pytype_ns, 'py:')
+            name = name.replace(xsi_ns, 'xsi:')
         result = result + "%s  * %s = %r\n" % (indentstr, name, value)
 
     indent = indent + 1
@@ -1097,6 +1098,9 @@
 
     if value is not None:
         dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, value)
+        if dict_result is NULL and ':' in value:
+            prefix, value = value.split(':', 1)
+            dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, value)
         if dict_result is not NULL:
             return (<PyType>dict_result)._type
 
@@ -1516,6 +1520,9 @@
 
         if value is not None:
             dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, value)
+            if dict_result is NULL and ':' in value:
+                prefix, value = value.split(':', 1)
+                dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, value)
             if dict_result is not NULL:
                 pytype = <PyType>dict_result
 
@@ -1574,6 +1581,9 @@
             c_node, _XML_SCHEMA_INSTANCE_NS, "type")
         if typename is not None:
             dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, typename)
+            if dict_result is NULL and ':' in typename:
+                prefix, typename = typename.split(':', 1)
+                dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, typename)
             if dict_result is not NULL:
                 pytype = <PyType>dict_result
                 if pytype is not StrType:
@@ -1617,6 +1627,15 @@
         cetree.delAttributeFromNsName(c_node, _XML_SCHEMA_INSTANCE_NS, "type")
     else:
         # update or create attribute
+        c_ns = cetree.findOrBuildNodeNs(doc, c_node, _XML_SCHEMA_NS)
+        if c_ns is not NULL:
+            if c_ns.prefix is not NULL and c_ns.prefix[0] != c'\0':
+                if ':' in typename:
+                    oldprefix, name = typename.split(':', 1)
+                    if cstd.strcmp(_cstr(oldprefix), c_ns.prefix) != 0:
+                        typename = c_ns.prefix + ':' + name
+            elif ':' in typename:
+                _, typename = typename.split(':', 1)
         c_ns = cetree.findOrBuildNodeNs(doc, c_node, _XML_SCHEMA_INSTANCE_NS)
         tree.xmlSetNsProp(c_node, c_ns, "type", _cstr(typename))
     tree.END_FOR_EACH_ELEMENT_FROM(c_node)
@@ -1729,6 +1748,7 @@
     if the type can be identified.  If '_pytype' or '_xsi' are among the
     keyword arguments, they will be used instead.
     """
+    cdef python.PyObject* dict_result
     if nsmap is None:
         nsmap = _DEFAULT_NSMAP
     if attrib is not None:
@@ -1736,12 +1756,30 @@
             attrib.update(_attributes)
         _attributes = attrib
     if _xsi is not None:
+        if ':' in _xsi:
+            prefix, name = _xsi.split(':', 1)
+            ns = nsmap.get(prefix)
+            if ns != XML_SCHEMA_NS:
+                raise TypeError, "XSD types require the XSD namespace"
+        elif nsmap is _DEFAULT_NSMAP:
+            name = _xsi
+            _xsi = 'xsd' + ':' + _xsi
+        else:
+            name = _xsi
+            for p, ns in nsmap.items():
+                if ns == XML_SCHEMA_NS:
+                    _xsi = prefix + ':' + _xsi
+                    break
+            else:
+                raise TypeError, "XSD types require the XSD namespace"
         python.PyDict_SetItem(_attributes, XML_SCHEMA_INSTANCE_TYPE_ATTR, _xsi)
         if _pytype is None:
-            # allow for s.o. using unregistered or even wrong xsi:type names
-            pytype_lookup = _SCHEMA_TYPE_DICT.get(_xsi)
-            if pytype_lookup is not None:
-                _pytype = pytype_lookup.name
+            # allow using unregistered or even wrong xsi:type names
+            dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, _xsi)
+            if dict_result is NULL:
+                dict_result = python.PyDict_GetItem(_SCHEMA_TYPE_DICT, name)
+            if dict_result is not NULL:
+                _pytype = (<PyType>dict_result).name
 
     if python._isString(_value):
         strval = _value


More information about the lxml-checkins mailing list