Fixed Beremiz for working with new xmlclass support using lxml
authorLaurent Bessard
Wed, 11 Sep 2013 23:48:41 +0200
changeset 1315 ff14a66bbd12
parent 1314 822d483197ad
child 1316 df9d02bd3eb7
Fixed Beremiz for working with new xmlclass support using lxml
CodeFileTreeNode.py
ConfigTreeNode.py
PLCControler.py
PLCGenerator.py
ProjectController.py
c_ext/c_ext.py
editors/ConfTreeNodeEditor.py
py_ext/PythonFileCTNMixin.py
py_ext/py_ext_xsd.xsd
targets/toolchain_gcc.py
xmlclass/xmlclass.py
xmlclass/xsdschema.py
--- a/CodeFileTreeNode.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/CodeFileTreeNode.py	Wed Sep 11 23:48:41 2013 +0200
@@ -1,13 +1,14 @@
-import os
-from xml.dom import minidom
-import cPickle
-
-from xmlclass import GenerateClassesFromXSDstring, UpdateXMLClassGlobals
+import os, re
+
+from copy import deepcopy
+from lxml import etree
+from xmlclass import GenerateParserFromXSDstring
 
 from PLCControler import UndoBuffer
 
 CODEFILE_XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:xhtml="http://www.w3.org/1999/xhtml">
   <xsd:element name="%(codefile_name)s">
     <xsd:complexType>
       <xsd:sequence>
@@ -65,22 +66,29 @@
             [SECTION_TAG_ELEMENT % name
              for name in self.SECTIONS_NAMES if name != "includes"])
         
-        self.CodeFileClasses = GenerateClassesFromXSDstring(
+        self.CodeFileParser = GenerateParserFromXSDstring(
             CODEFILE_XSD % sections_str)
+        self.CodeFileVariables = etree.XPath("variables/variable")
         
         filepath = self.CodeFileName()
         
-        self.CodeFile = self.CodeFileClasses[self.CODEFILE_NAME]()
         if os.path.isfile(filepath):
             xmlfile = open(filepath, 'r')
-            tree = minidom.parse(xmlfile)
+            codefile_xml = xmlfile.read()
             xmlfile.close()
             
-            for child in tree.childNodes:
-                if child.nodeType == tree.ELEMENT_NODE and child.nodeName in [self.CODEFILE_NAME]:
-                    self.CodeFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
-                    self.CreateCodeFileBuffer(True)
+            codefile_xml = codefile_xml.replace(
+                '<%s>' % self.CODEFILE_NAME, 
+                '<%s xmlns:xhtml="http://www.w3.org/1999/xhtml">' % self.CODEFILE_NAME)
+            for cre, repl in [
+                (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
+                (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
+                codefile_xml = cre.sub(repl, codefile_xml)
+            self.CodeFile = etree.fromstring(codefile_xml, self.CodeFileParser)    
+            self.CreateCodeFileBuffer(True)
+        
         else:
+            self.CodeFile = self.CodeFileParser.CreateRoot()
             self.CreateCodeFileBuffer(False)
             self.OnCTNSave()
 
@@ -99,7 +107,7 @@
     def SetVariables(self, variables):
         self.CodeFile.variables.setvariable([])
         for var in variables:
-            variable = self.CodeFileClasses["variables_variable"]()
+            variable = self.CodeFileParser.CreateElement("variable", "variables")
             variable.setname(var["Name"])
             variable.settype(var["Type"])
             variable.setinitial(var["Initial"])
@@ -107,7 +115,7 @@
     
     def GetVariables(self):
         datas = []
-        for var in self.CodeFile.variables.getvariable():
+        for var in self.CodeFileVariables(self.CodeFile):
             datas.append({"Name" : var.getname(), 
                           "Type" : var.gettype(), 
                           "Initial" : var.getinitial()})
@@ -117,10 +125,10 @@
         for section in self.SECTIONS_NAMES:
             section_code = parts.get(section)
             if section_code is not None:
-                getattr(self.CodeFile, section).settext(section_code)
+                getattr(self.CodeFile, section).setanyText(section_code)
     
     def GetTextParts(self):
-        return dict([(section, getattr(self.CodeFile, section).gettext())
+        return dict([(section, getattr(self.CodeFile, section).getanyText())
                      for section in self.SECTIONS_NAMES])
             
     def CTNTestModified(self):
@@ -129,11 +137,12 @@
     def OnCTNSave(self, from_project_path=None):
         filepath = self.CodeFileName()
         
-        text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-        text += self.CodeFile.generateXMLText(self.CODEFILE_NAME, 0)
-
         xmlfile = open(filepath,"w")
-        xmlfile.write(text.encode("utf-8"))
+        xmlfile.write(etree.tostring(
+            self.CodeFile, 
+            pretty_print=True, 
+            xml_declaration=True, 
+            encoding='utf-8'))
         xmlfile.close()
         
         self.MarkCodeFileAsSaved()
@@ -144,39 +153,31 @@
         return [(variable.getname(),
                  variable.gettype(),
                  variable.getinitial())
-                for variable in self.CodeFile.variables.variable]
+                for variable in self.CodeFileVariables(self.CodeFile)]
 
 #-------------------------------------------------------------------------------
 #                      Current Buffering Management Functions
 #-------------------------------------------------------------------------------
 
-    def cPickle_loads(self, str_obj):
-        UpdateXMLClassGlobals(self.CodeFileClasses)
-        return cPickle.loads(str_obj)
-
-    def cPickle_dumps(self, obj):
-        UpdateXMLClassGlobals(self.CodeFileClasses)
-        return cPickle.dumps(obj)
-
     """
     Return a copy of the codefile model
     """
     def Copy(self, model):
-        return self.cPickle_loads(self.cPickle_dumps(model))
+        return deepcopy(model)
 
     def CreateCodeFileBuffer(self, saved):
         self.Buffering = False
-        self.CodeFileBuffer = UndoBuffer(self.cPickle_dumps(self.CodeFile), saved)
+        self.CodeFileBuffer = UndoBuffer(self.CodeFileParser.Dumps(self.CodeFile), saved)
 
     def BufferCodeFile(self):
-        self.CodeFileBuffer.Buffering(self.cPickle_dumps(self.CodeFile))
+        self.CodeFileBuffer.Buffering(self.CodeFileParser.Dumps(self.CodeFile))
     
     def StartBuffering(self):
         self.Buffering = True
         
     def EndBuffering(self):
         if self.Buffering:
-            self.CodeFileBuffer.Buffering(self.cPickle_dumps(self.CodeFile))
+            self.CodeFileBuffer.Buffering(self.CodeFileParser.Dumps(self.CodeFile))
             self.Buffering = False
     
     def MarkCodeFileAsSaved(self):
@@ -188,10 +189,10 @@
         
     def LoadPrevious(self):
         self.EndBuffering()
-        self.CodeFile = self.cPickle_loads(self.CodeFileBuffer.Previous())
+        self.CodeFile = self.CodeFileParser.Loads(self.CodeFileBuffer.Previous())
     
     def LoadNext(self):
-        self.CodeFile = self.cPickle_loads(self.CodeFileBuffer.Next())
+        self.CodeFile = self.CodeFileParser.Loads(self.CodeFileBuffer.Next())
     
     def GetBufferState(self):
         first = self.CodeFileBuffer.IsFirst() and not self.Buffering
--- a/ConfigTreeNode.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/ConfigTreeNode.py	Wed Sep 11 23:48:41 2013 +0200
@@ -9,15 +9,15 @@
 
 import os,traceback,types
 import shutil
-from xml.dom import minidom
-
-from xmlclass import GenerateClassesFromXSDstring
+from lxml import etree
+
+from xmlclass import GenerateParserFromXSDstring
 from util.misc import GetClassImporter
 
 from PLCControler import PLCControler, LOCATION_CONFNODE
 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
 
-_BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
+_BaseParamsParser = GenerateParserFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
           <xsd:element name="BaseParams">
             <xsd:complexType>
@@ -26,7 +26,7 @@
               <xsd:attribute name="Enabled" type="xsd:boolean" use="optional" default="true"/>
             </xsd:complexType>
           </xsd:element>
-        </xsd:schema>""")["BaseParams"]
+        </xsd:schema>""")
 
 NameTypeSeparator = '@'
 
@@ -46,17 +46,15 @@
     def _AddParamsMembers(self):
         self.CTNParams = None
         if self.XSD:
-            self.Classes = GenerateClassesFromXSDstring(self.XSD)
-            Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
-            if len(Classes) == 1:
-                name, XSDclass = Classes[0]
-                obj = XSDclass()
-                self.CTNParams = (name, obj)
-                setattr(self, name, obj)
+            self.Parser = GenerateParserFromXSDstring(self.XSD)
+            obj = self.Parser.CreateRoot()
+            name = obj.getLocalTag()
+            self.CTNParams = (name, obj)
+            setattr(self, name, obj)
 
     def __init__(self):
         # Create BaseParam 
-        self.BaseParams = _BaseParamsClass()
+        self.BaseParams = _BaseParamsParser.CreateRoot()
         self.MandatoryParams = ("BaseParams", self.BaseParams)
         self._AddParamsMembers()
         self.Children = {}
@@ -170,15 +168,21 @@
             # generate XML for base XML parameters controller of the confnode
             if self.MandatoryParams:
                 BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
-                BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
-                BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
+                BaseXMLFile.write(etree.tostring(
+                    self.MandatoryParams[1], 
+                    pretty_print=True, 
+                    xml_declaration=True, 
+                    encoding='utf-8'))
                 BaseXMLFile.close()
             
             # generate XML for XML parameters controller of the confnode
             if self.CTNParams:
                 XMLFile = open(self.ConfNodeXmlFilePath(),'w')
-                XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
-                XMLFile.write(self.CTNParams[1].generateXMLText(self.CTNParams[0], 0).encode("utf-8"))
+                XMLFile.write(etree.tostring(
+                    self.CTNParams[1], 
+                    pretty_print=True, 
+                    xml_declaration=True, 
+                    encoding='utf-8'))
                 XMLFile.close()
             
             # Call the confnode specific OnCTNSave method
@@ -581,8 +585,9 @@
         if self.MandatoryParams:
             try:
                 basexmlfile = open(self.ConfNodeBaseXmlFilePath(CTNName), 'r')
-                basetree = minidom.parse(basexmlfile)
-                self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
+                self.BaseParams = etree.fromstring(
+                    basexmlfile.read(), _BaseParamsParser)
+                self.MandatoryParams = ("BaseParams", self.BaseParams)
                 basexmlfile.close()
             except Exception, exc:
                 self.GetCTRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (CTNName, unicode(exc)))
@@ -592,8 +597,10 @@
         if self.CTNParams:
             try:
                 xmlfile = open(self.ConfNodeXmlFilePath(CTNName), 'r')
-                tree = minidom.parse(xmlfile)
-                self.CTNParams[1].loadXMLTree(tree.childNodes[0])
+                obj = etree.fromstring(xmlfile.read(), self.Parser)
+                name = obj.getLocalTag()
+                setattr(self, name, obj)
+                self.CTNParams = (name, obj)
                 xmlfile.close()
             except Exception, exc:
                 self.GetCTRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (CTNName, unicode(exc)))
--- a/PLCControler.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/PLCControler.py	Wed Sep 11 23:48:41 2013 +0200
@@ -1501,9 +1501,9 @@
             tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
             tempvar.setname(var_name)
             
-            tempvartype = PLCOpenParser.CreateElement("dataType", "variable")
+            tempvartype = PLCOpenParser.CreateElement("type", "variable")
             if var_type in self.GetBaseTypes():
-                tempvar.setcontent(PLCOpenParser.CreateElement(
+                tempvartype.setcontent(PLCOpenParser.CreateElement(
                     var_type.lower()
                     if var_type in ["STRING", "WSTRING"]
                     else var_type, "dataType"))
--- a/PLCGenerator.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/PLCGenerator.py	Wed Sep 11 23:48:41 2013 +0200
@@ -271,10 +271,15 @@
         varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()]
         
         extra_variables = self.Controler.GetConfigurationExtraVariables()
-        if len(extra_variables) > 0:
-            if len(varlists) == 0:
-                varlists = [(PLCOpenParser.CreateElement("globalVars", "interface"), [])]
-            varlists[-1][1].extend(extra_variables)
+        extra_global_vars = None
+        if len(extra_variables) > 0 and len(varlists) == 0:
+            extra_global_vars = PLCOpenParser.CreateElement("globalVars", "interface")
+            configuration.setglobalVars([extra_global_vars])
+            varlists = [(extra_global_vars, [])]
+            
+        for variable in extra_variables:
+            varlists[-1][0].appendvariable(variable)
+            varlists[-1][1].append(variable)
             
         # Generate any global variable in configuration
         for varlist, varlist_variables in varlists:
@@ -310,12 +315,19 @@
                            (var.gettypeAsText(), (tagname, variable_type, var_number, "type"))]
                 # Generate variable initial value if exists
                 initial = var.getinitialValue()
-                if initial:
+                if initial is not None:
                     config += [(" := ", ()),
                                (self.ComputeValue(initial.getvalue(), var_type), (tagname, variable_type, var_number, "initial value"))]
                 config += [(";\n", ())]
                 var_number += 1
             config += [("  END_VAR\n", ())]
+        
+        if extra_global_vars is not None:
+            configuration.remove(extra_global_vars)
+        else:
+            for variable in extra_variables:
+                varlists[-1][1].remove(variable)
+        
         # Generate any resource in the configuration
         for resource in configuration.getresource():
             config += self.GenerateResource(resource, configuration.getname())
@@ -363,7 +375,7 @@
                            (var.gettypeAsText(), (tagname, variable_type, var_number, "type"))]
                 # Generate variable initial value if exists
                 initial = var.getinitialValue()
-                if initial:
+                if initial is not None:
                     resrce += [(" := ", ()),
                                (self.ComputeValue(initial.getvalue(), var_type), (tagname, variable_type, var_number, "initial value"))]
                 resrce += [(";\n", ())]
@@ -380,13 +392,13 @@
             args = []
             single = task.getsingle()
             # Single argument if exists
-            if single:
+            if single is not None:
                 resrce += [("SINGLE := ", ()),
                            (single, (tagname, "task", task_number, "single")),
                            (",", ())]
             # Interval argument if exists
             interval = task.getinterval()
-            if interval:
+            if interval is not None:
                 resrce += [("INTERVAL := ", ()),
                            (interval, (tagname, "task", task_number, "interval")),
                            (",", ())]
--- a/ProjectController.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/ProjectController.py	Wed Sep 11 23:48:41 2013 +0200
@@ -221,9 +221,11 @@
     def GetTarget(self):
         target = self.BeremizRoot.getTargetType()
         if target.getcontent() is None:
-            target = self.Classes["BeremizRoot_TargetType"]()
+            temp_root = self.Parser.CreateRoot()
+            target = self.Parser.CreateElement("TargetType", "BeremizRoot")
+            temp_root.setTargetType(target)
             target_name = self.GetDefaultTargetName()
-            target.setcontent({"name": target_name, "value": self.Classes["TargetType_%s"%target_name]()})
+            target.setcontent(self.Parser.CreateElement(target_name, "TargetType"))
         return target
     
     def GetParamsAttributes(self, path = None):
@@ -659,7 +661,7 @@
         Return a Builder (compile C code into machine code)
         """
         # Get target, module and class name
-        targetname = self.GetTarget().getcontent()["name"]
+        targetname = self.GetTarget().getcontent().getLocalTag()
         targetclass = targets.GetBuilder(targetname)
 
         # if target already 
@@ -861,7 +863,7 @@
                 "init_calls":"\n",
                 "cleanup_calls":"\n"
                 }
-        plc_main_code += targets.GetTargetCode(self.GetTarget().getcontent()["name"])
+        plc_main_code += targets.GetTargetCode(self.GetTarget().getcontent().getLocalTag())
         plc_main_code += targets.GetCode("plc_main_tail")
         return plc_main_code
 
--- a/c_ext/c_ext.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/c_ext/c_ext.py	Wed Sep 11 23:48:41 2013 +0200
@@ -25,9 +25,6 @@
         "publishFunction"]
     EditorType = CFileEditor
     
-    def GenerateClassesFromXSDstring(self, xsd_string):
-        return GenerateClassesFromXSDstring(xsd_string)
-    
     def GetIconName(self):
         return "Cfile"
 
@@ -56,7 +53,7 @@
         
         # Adding includes
         text += "/* User includes */\n"
-        text += self.CodeFile.includes.gettext().strip()
+        text += self.CodeFile.includes.getanyText().strip()
         text += "\n"
         
         text += '#include "iec_types_all.h"\n\n'
@@ -76,25 +73,25 @@
         
         # Adding user global variables and routines
         text += "/* User internal user variables and routines */\n"
-        text += self.CodeFile.globals.gettext().strip()
+        text += self.CodeFile.globals.getanyText().strip()
         text += "\n"
         
         # Adding Beremiz confnode functions
         text += "/* Beremiz confnode functions */\n"
         text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
-        text += self.CodeFile.initFunction.gettext().strip()
+        text += self.CodeFile.initFunction.getanyText().strip()
         text += "  return 0;\n}\n\n"
         
         text += "void __cleanup_%s(void)\n{\n"%location_str
-        text += self.CodeFile.cleanUpFunction.gettext().strip()
+        text += self.CodeFile.cleanUpFunction.getanyText().strip()
         text += "\n}\n\n"
         
         text += "void __retrieve_%s(void)\n{\n"%location_str
-        text += self.CodeFile.retrieveFunction.gettext().strip()
+        text += self.CodeFile.retrieveFunction.getanyText().strip()
         text += "\n}\n\n"
         
         text += "void __publish_%s(void)\n{\n"%location_str
-        text += self.CodeFile.publishFunction.gettext().strip()
+        text += self.CodeFile.publishFunction.getanyText().strip()
         text += "\n}\n\n"
         
         Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
--- a/editors/ConfTreeNodeEditor.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/editors/ConfTreeNodeEditor.py	Wed Sep 11 23:48:41 2013 +0200
@@ -496,6 +496,8 @@
     def GetChoiceCallBackFunction(self, choicectrl, path):
         def OnChoiceChanged(event):
             res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
+            if res is None:
+                res = ""
             choicectrl.SetStringSelection(res)
             event.Skip()
         return OnChoiceChanged
--- a/py_ext/PythonFileCTNMixin.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/py_ext/PythonFileCTNMixin.py	Wed Sep 11 23:48:41 2013 +0200
@@ -1,15 +1,11 @@
-import os
-from PLCControler import UndoBuffer
+import os, re
+from lxml import etree
+
+from xmlclass import GenerateParserFromXSD
+
+from CodeFileTreeNode import CodeFile
 from PythonEditor import PythonEditor
 
-from xml.dom import minidom
-from xmlclass import GenerateClassesFromXSD
-import cPickle
-
-from CodeFileTreeNode import CodeFile
-
-PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd")) 
-
 class PythonFileCTNMixin(CodeFile):
     
     CODEFILE_NAME = "PyFile"
@@ -26,19 +22,27 @@
         
         filepath = self.PythonFileName()
         
-        python_code = PythonClasses["Python"]()
         if os.path.isfile(filepath):
+            PythonParser = GenerateParserFromXSD(
+                os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd")) 
+            
             xmlfile = open(filepath, 'r')
-            tree = minidom.parse(xmlfile)
+            pythonfile_xml = xmlfile.read()
             xmlfile.close()
             
-            for child in tree.childNodes:
-                if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
-                    python_code.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
-                    self.CodeFile.globals.settext(python_code.gettext())
-                    os.remove(filepath)
-                    self.CreateCodeFileBuffer(False)
-                    self.OnCTNSave()
+            pythonfile_xml = pythonfile_xml.replace(
+                'xmlns="http://www.w3.org/2001/XMLSchema"', 
+                'xmlns:xhtml="http://www.w3.org/1999/xhtml"')
+            for cre, repl in [
+                (re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
+                (re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
+                pythonfile_xml = cre.sub(repl, pythonfile_xml)
+            python_code = etree.fromstring(pythonfile_xml, PythonParser)
+            
+            self.CodeFile.globals.setanyText(python_code.getanyText())
+            os.remove(filepath)
+            self.CreateCodeFileBuffer(False)
+            self.OnCTNSave()
     
     def CodeFileName(self):
         return os.path.join(self.CTNPath(), "pyfile.xml")
@@ -50,7 +54,7 @@
     PostSectionsTexts = {}
     def GetSection(self,section):
         return self.PreSectionsTexts.get(section,"") + "\n" + \
-               getattr(self.CodeFile, section).gettext() + "\n" + \
+               getattr(self.CodeFile, section).getanyText() + "\n" + \
                self.PostSectionsTexts.get(section,"")
         
 
--- a/py_ext/py_ext_xsd.xsd	Tue Sep 10 23:23:45 2013 +0200
+++ b/py_ext/py_ext_xsd.xsd	Wed Sep 11 23:48:41 2013 +0200
@@ -1,18 +1,14 @@
 <?xml version="1.0" encoding="ISO-8859-1" ?>
-<xsd:schema targetNamespace="python_xsd.xsd" 
-            xmlns:cext="python_xsd.xsd" 
-            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-            elementFormDefault="qualified" 
-            attributeFormDefault="unqualified">
-
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:xhtml="http://www.w3.org/1999/xhtml">
   <xsd:element name="Python">
-	  <xsd:complexType>
-	    <xsd:annotation>
-	      <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
-	    </xsd:annotation>
-	    <xsd:sequence>
-	      <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
-	    </xsd:sequence>
-	  </xsd:complexType>
-	</xsd:element>
+    <xsd:complexType>
+      <xsd:annotation>
+        <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
+      </xsd:annotation>
+      <xsd:sequence>
+        <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
+      </xsd:sequence>
+    </xsd:complexType>
+  </xsd:element>
 </xsd:schema>
--- a/targets/toolchain_gcc.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/targets/toolchain_gcc.py	Wed Sep 11 23:48:41 2013 +0200
@@ -19,14 +19,14 @@
         """
         Returns list of builder specific CFLAGS
         """
-        return [self.CTRInstance.GetTarget().getcontent()["value"].getCFLAGS()]
+        return [self.CTRInstance.GetTarget().getcontent().getCFLAGS()]
 
     def getBuilderLDFLAGS(self):
         """
         Returns list of builder specific LDFLAGS
         """
         return self.CTRInstance.LDFLAGS + \
-               [self.CTRInstance.GetTarget().getcontent()["value"].getLDFLAGS()]
+               [self.CTRInstance.GetTarget().getcontent().getLDFLAGS()]
 
     def GetBinaryCode(self):
         try:
@@ -89,7 +89,7 @@
                 
     def build(self):
         # Retrieve toolchain user parameters
-        toolchain_params = self.CTRInstance.GetTarget().getcontent()["value"]
+        toolchain_params = self.CTRInstance.GetTarget().getcontent()
         self.compiler = toolchain_params.getCompiler()
         self.linker = toolchain_params.getLinker()
 
--- a/xmlclass/xmlclass.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/xmlclass/xmlclass.py	Wed Sep 11 23:48:41 2013 +0200
@@ -610,7 +610,7 @@
                 value = infos["elmt_type"]["initial"]()
                 if infos["type"] != ANY:
                     DefaultElementClass.__setattr__(value, "tag", element_name)
-                    value.init()
+                    value._init_()
                 return value
         return [initial_value() for i in xrange(infos["minOccurs"])]
     else:
@@ -664,7 +664,9 @@
             if choices_dict.has_key(choice_name):
                 raise ValueError("'%s' element defined two times in choice" % choice_name)
             choices_dict[choice_name] = infos
-    choices_xpath = "|".join(map(lambda x: "%s:%s" % (factory.TargetNamespace, x), choices_dict.keys()))
+    prefix = ("%s:" % factory.TargetNamespace
+              if factory.TargetNamespace is not None else "")
+    choices_xpath = "|".join(map(lambda x: prefix + x, choices_dict.keys()))
     
     def GetContentInitial():
         content_name, infos = choices[0]
@@ -1127,7 +1129,7 @@
             classmembers["set%s" % elmtname] = generateSetMethod(elmtname)
             classmembers["get%s" % elmtname] = generateGetMethod(elmtname)
             
-        classmembers["init"] = generateInitMethod(self, classinfos)
+        classmembers["_init_"] = generateInitMethod(self, classinfos)
         classmembers["getElementAttributes"] = generateGetElementAttributes(self, classinfos)
         classmembers["getElementInfos"] = generateGetElementInfos(self, classinfos)
         classmembers["setElementValue"] = generateSetElementValue(self, classinfos)
@@ -1251,7 +1253,9 @@
                 element_infos["elmt_type"]["generate"](self, value)
             
             else:
-                element_xpath = ("%s:%s" % (factory.TargetNamespace, name)
+                prefix = ("%s:" % factory.TargetNamespace
+                          if factory.TargetNamespace is not None else "")
+                element_xpath = (prefix + name
                                  if name != "content"
                                  else elements["content"]["elmt_type"]["choices_xpath"].path)
                 
@@ -1262,7 +1266,7 @@
                     element_idx = elements.keys().index(name)
                     if element_idx > 0:
                         previous_elements_xpath = "|".join(map(
-                            lambda x: "%s:%s" % (factory.TargetNamespace, x)
+                            lambda x: prefix + x
                                       if x != "content"
                                       else elements["content"]["elmt_type"]["choices_xpath"].path,
                             elements.keys()[:element_idx]))
@@ -1341,7 +1345,7 @@
                                              elements[parts[0]]["elmt_type"]["facets"])
                     value = getattr(self, parts[0], "")
                 elif parts[0] == "content":
-                    return self.content["value"].getElementInfos(self.content["name"], path)
+                    return self.content.getElementInfos(self.content.getLocalTag(), path)
                 else:
                     attr = getattr(self, parts[0], None)
                     if attr is None:
@@ -1352,7 +1356,7 @@
                         return attr.getElementInfos(parts[0], parts[1])
             elif elements.has_key("content"):
                 if len(parts) > 0:
-                    return self.content["value"].getElementInfos(name, path)
+                    return self.content.getElementInfos(name, path)
             elif classinfos.has_key("base"):
                 classinfos["base"].getElementInfos(name, path)
             else:
@@ -1370,15 +1374,9 @@
                     if self.content is None:
                         value = ""
                     else:
-                        value = self.content["name"]
-                        if self.content["value"] is not None:
-                            if self.content["name"] == "sequence":
-                                choices_dict = dict([(choice["name"], choice) for choice in element["choices"]])
-                                sequence_infos = choices_dict.get("sequence", None)
-                                if sequence_infos is not None:
-                                    children.extend([item.getElementInfos(infos["name"]) for item, infos in zip(self.content["value"], sequence_infos["elements"])])
-                            else:
-                                children.extend(self.content["value"].getElementInfos(self.content["name"])["children"])
+                        value = self.content.getLocalTag()
+                        if self.content is not None:
+                            children.extend(self.content.getElementInfos(value)["children"])
                 elif element["elmt_type"]["type"] == SIMPLETYPE:
                     children.append({"name": element_name, "require": element["minOccurs"] != 0, 
                         "type": gettypeinfos(element["elmt_type"]["basename"], 
@@ -1435,13 +1433,13 @@
                             instance.setElementValue(None, value)
             elif elements.has_key("content"):
                 if len(parts) > 0:
-                    self.content["value"].setElementValue(path, value)
+                    self.content.setElementValue(path, value)
             elif classinfos.has_key("base"):
                 classinfos["base"].setElementValue(self, path, value)
         elif elements.has_key("content"):
             if value == "":
                 if elements["content"]["minOccurs"] == 0:
-                    self.setcontent(None)
+                    self.setcontent([])
                 else:
                     raise ValueError("\"content\" element is required!")
             else:
@@ -1454,7 +1452,7 @@
 def generateInitMethod(factory, classinfos):
     def initMethod(self):
         if classinfos.has_key("base"):
-            classinfos["base"].init(self)
+            classinfos["base"]._init_(self)
         for attribute in classinfos["attributes"]:
             attribute["attr_type"] = FindTypeInfos(factory, attribute["attr_type"])
             if attribute["use"] == "required":
@@ -1491,7 +1489,7 @@
             value = infos["elmt_type"]["initial"]()
             DefaultElementClass.__setattr__(value, "tag", factory.etreeNamespaceFormat % attr)
             setattr(self, attr, value)
-            value.init()
+            value._init_()
         else:
             raise ValueError("Invalid class attribute!")
     return addMethod
@@ -1541,6 +1539,7 @@
             raise ValueError("Unknown \"%s\" choice type for \"content\"!" % content_type)
         choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
         new_content = choices[content_type]["elmt_type"]["initial"]()
+        DefaultElementClass.__setattr__(new_content, "tag", factory.etreeNamespaceFormat % content_type)
         self.content = new_content
         return new_content
     return setChoiceMethod
@@ -1553,6 +1552,7 @@
         choices[content_type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
             new_element = choices[content_type]["elmt_type"]["initial"]()
+            DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type)
             self.appendcontent(new_element)
             return new_element
         else:
@@ -1567,6 +1567,7 @@
         choices[type]["elmt_type"] = FindTypeInfos(factory, choices[content_type]["elmt_type"])
         if maxOccurs == "unbounded" or len(self.content) < maxOccurs:
             new_element = choices[content_type]["elmt_type"]["initial"]()
+            DefaultElementClass.__setattr__(new_element, "tag", factory.etreeNamespaceFormat % content_type)
             self.insertcontent(index, new_element)
             return new_element
         else:
@@ -1595,7 +1596,7 @@
 
 class DefaultElementClass(etree.ElementBase):
     
-    def init(self):
+    def _init_(self):
         pass
     
     def getLocalTag(self):
@@ -1657,7 +1658,7 @@
             root = self.makeelement(
                 self.DefaultNamespaceFormat % self.BaseClass[0],
                 nsmap=self.RootNSMAP)
-            root.init()
+            root._init_()
             return root
         return None
     
@@ -1671,16 +1672,14 @@
     def CreateElement(self, element_tag, parent_tag=None):
         new_element = self.GetElementClass(element_tag, parent_tag)()
         DefaultElementClass.__setattr__(new_element, "tag", self.DefaultNamespaceFormat % element_tag)
-        new_element.init()
+        new_element._init_()
         return new_element
     
 def GenerateParser(factory, xsdstring):
     ComputedClasses = factory.CreateClasses()
     if factory.FileName is not None and len(ComputedClasses) == 1:
         ComputedClasses = ComputedClasses[factory.FileName]
-        BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
-    else:
-        BaseClass = []
+    BaseClass = [(name, XSDclass) for name, XSDclass in ComputedClasses.items() if XSDclass.IsBaseClass]
     UpdateXMLClassGlobals(ComputedClasses)
     
     parser = XMLClassParser(
--- a/xmlclass/xsdschema.py	Tue Sep 10 23:23:45 2013 +0200
+++ b/xmlclass/xsdschema.py	Wed Sep 11 23:48:41 2013 +0200
@@ -939,9 +939,10 @@
     factory.BlockDefault = attributes["blockDefault"]
     factory.FinalDefault = attributes["finalDefault"]
     
-    factory.TargetNamespace = factory.DefinedNamespaces.get(attributes["targetNamespace"], None)
+    targetNamespace = attributes.get("targetNamespace", None)
+    factory.TargetNamespace = factory.DefinedNamespaces.get(targetNamespace, None)
     if factory.TargetNamespace is not None:
-        factory.etreeNamespaceFormat = "{%s}%%s" % attributes["targetNamespace"]
+        factory.etreeNamespaceFormat = "{%s}%%s" % targetNamespace
     factory.Namespaces[factory.TargetNamespace] = {}
     
     annotations, children = factory.ReduceElements(elements, True)
@@ -1097,7 +1098,7 @@
 This function generate a xml from the xsd given as a string
 """
 def GenerateParserFromXSDstring(xsdstring):
-    return GenerateParser(XSDClassFactory(minidom.parseString(xsdstring)))
+    return GenerateParser(XSDClassFactory(minidom.parseString(xsdstring)), xsdstring)
 
 
 #-------------------------------------------------------------------------------
@@ -2521,19 +2522,3 @@
     "anyType": {"type": COMPLEXTYPE, "extract": lambda x:None},
 }
 
-if __name__ == '__main__':
-    classes = GenerateClassesFromXSD("test.xsd")
-    
-    # Code for test of test.xsd
-    xmlfile = open("po.xml", 'r')
-    tree = minidom.parse(xmlfile)
-    xmlfile.close()
-    test = classes["PurchaseOrderType"]()
-    for child in tree.childNodes:
-        if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "purchaseOrder":
-            test.loadXMLTree(child)
-    test.items.item[0].setquantity(2)
-    testfile = open("test.xml", 'w')
-    testfile.write(u'<?xml version=\"1.0\"?>\n')
-    testfile.write(test.generateXMLText("purchaseOrder").encode("utf-8"))
-    testfile.close()