Fixed controllers for working with latest version of xmlclass
authorLaurent Bessard
Tue, 24 Sep 2013 00:48:21 +0200
changeset 2157 a2385e535cf5
parent 2156 c8eee6be2da8
child 2158 7132aa34188d
Fixed controllers for working with latest version of xmlclass
etherlab/EthercatMaster.py
etherlab/entries_list.xslt
etherlab/etherlab.py
--- a/etherlab/EthercatMaster.py	Tue Jun 25 00:55:38 2013 +0200
+++ b/etherlab/EthercatMaster.py	Tue Sep 24 00:48:21 2013 +0200
@@ -1,6 +1,7 @@
 import os
 import cPickle
-from xml.dom import minidom
+from lxml import etree
+from copy import deepcopy
 
 import wx
 
@@ -81,14 +82,14 @@
 #                 Ethercat MASTER
 #--------------------------------------------------
 
-EtherCATConfigClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) 
+EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) 
 
 def sort_commands(x, y):
     if x["Index"] == y["Index"]:
         return cmp(x["Subindex"], y["Subindex"])
     return cmp(x["Index"], y["Index"])
 
-cls = EtherCATConfigClasses.get("Config_Slave", None)
+cls = EtherCATConfigParser.GetElementClass("Slave", "Config")
 if cls:
     
     def getType(self):
@@ -152,12 +153,12 @@
     
     def appendStartupCommand(self, command_infos):
         InitCmds = self.getInitCmds(True)
-        command = EtherCATConfigClasses["InitCmds_InitCmd"]()
+        command = EtherCATConfigParser.CreateElement("InitCmd", "InitCmds", 1)
+        InitCmds.appendInitCmd(command)
         command.setIndex(command_infos["Index"])
         command.setSubIndex(command_infos["Subindex"])
         command.setData(command_infos["Value"])
         command.setComment(command_infos["Description"])
-        InitCmds.appendInitCmd(command)
         return len(InitCmds.getInitCmd()) - 1
     setattr(cls, "appendStartupCommand", appendStartupCommand)
     
@@ -206,7 +207,7 @@
     </xsd:schema>
 """
 
-ProcessVariablesClasses = GenerateClassesFromXSDstring(ProcessVariablesXSD) 
+ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD) 
 
 class _EthercatCTN:
 
@@ -218,29 +219,27 @@
     def __init__(self):
         config_filepath = self.ConfigFileName()
         config_is_saved = False
-        self.Config = EtherCATConfigClasses["EtherCATConfig"]()
         if os.path.isfile(config_filepath):
             config_xmlfile = open(config_filepath, 'r')
-            config_tree = minidom.parse(config_xmlfile)
+            self.Config = etree.fromstring(
+                config_xmlfile.read(), EtherCATConfigParser)
+            config_is_saved = True
             config_xmlfile.close()
-            
-            for child in config_tree.childNodes:
-                if child.nodeType == config_tree.ELEMENT_NODE and child.nodeName == "EtherCATConfig":
-                    self.Config.loadXMLTree(child)
-                    config_is_saved = True
+        
+        else:
+            self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig")
         
         process_filepath = self.ProcessVariablesFileName()
         process_is_saved = False
-        self.ProcessVariables = ProcessVariablesClasses["ProcessVariables"]()
         if os.path.isfile(process_filepath):
             process_xmlfile = open(process_filepath, 'r')
-            process_tree = minidom.parse(process_xmlfile)
+            self.ProcessVariables = etree.fromstring(
+                process_xmlfile.read(), ProcessVariablesParser)
+            process_is_saved = True
             process_xmlfile.close()
             
-            for child in process_tree.childNodes:
-                if child.nodeType == process_tree.ELEMENT_NODE and child.nodeName == "ProcessVariables":
-                    self.ProcessVariables.loadXMLTree(child)
-                    process_is_saved = True
+        else:
+            self.ProcessVariables = ProcessVariablesParser.CreateElement("ProcessVariables")
         
         if config_is_saved and process_is_saved:
             self.CreateBuffer(True)
@@ -352,7 +351,7 @@
     def SetProcessVariables(self, variables):
         vars = []
         for var in variables:
-            variable = ProcessVariablesClasses["ProcessVariables_variable"]()
+            variable = ProcessVariablesParser.CreateElement("variable", "ProcessVariables")
             variable.setName(var["Name"])
             variable.setComment(var["Description"])
             if var["ReadFrom"] != "":
@@ -456,12 +455,12 @@
         
         slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
         if slave is None:
-            slave = EtherCATConfigClasses["Config_Slave"]()
+            slave = EtherCATConfigParser.CreateElement("Slave", "Config")
+            self.Config.getConfig().appendSlave(slave)
             slave_infos = slave.getInfo()
             slave_infos.setName("undefined")
             slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
             slave_infos.setAutoIncAddr(0)
-            self.Config.getConfig().appendSlave(slave)
             self.BufferModel()
             self.OnCTNSave()
         
@@ -542,6 +541,7 @@
                 type_infos = slave.getType()
                 device, module_extra_params = self.GetModuleInfos(type_infos)
         if device is not None:
+            print "Get Entries List", limits
             entries = device.GetEntriesList(limits)
             #print entries
             entries_list = entries.items()
@@ -647,23 +647,22 @@
     def OnCTNSave(self, from_project_path=None):
         config_filepath = self.ConfigFileName()
         
-        config_text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-        config_extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
-                  "xsi:noNamespaceSchemaLocation" : "EtherCATInfo.xsd"}
-        config_text += self.Config.generateXMLText("EtherCATConfig", 0, config_extras)
-
         config_xmlfile = open(config_filepath,"w")
-        config_xmlfile.write(config_text.encode("utf-8"))
+        config_xmlfile.write(etree.tostring(
+            self.Config, 
+            pretty_print=True, 
+            xml_declaration=True, 
+            encoding='utf-8'))
         config_xmlfile.close()
         
         process_filepath = self.ProcessVariablesFileName()
         
-        process_text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-        process_extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"}
-        process_text += self.ProcessVariables.generateXMLText("ProcessVariables", 0, process_extras)
-
         process_xmlfile = open(process_filepath,"w")
-        process_xmlfile.write(process_text.encode("utf-8"))
+        process_xmlfile.write(etree.tostring(
+            self.ProcessVariables, 
+            pretty_print=True, 
+            xml_declaration=True, 
+            encoding='utf-8'))
         process_xmlfile.close()
         
         self.Buffer.CurrentSaved()
@@ -751,13 +750,18 @@
     Return a copy of the config
     """
     def Copy(self, model):
-        return cPickle.loads(cPickle.dumps(model))
+        return deepcopy(model)
     
     def CreateBuffer(self, saved):
-        self.Buffer = UndoBuffer(cPickle.dumps((self.Config, self.ProcessVariables)), saved)
+        self.Buffer = UndoBuffer(
+            (EtherCATConfigParser.Dumps(self.Config), 
+             ProcessVariablesParser.Dumps(self.ProcessVariables)), 
+            saved)
         
     def BufferModel(self):
-        self.Buffer.Buffering(cPickle.dumps((self.Config, self.ProcessVariables)))
+        self.Buffer.Buffering(
+            (EtherCATConfigParser.Dumps(self.Config), 
+             ProcessVariablesParser.Dumps(self.ProcessVariables)))
     
     def ModelIsSaved(self):
         if self.Buffer is not None:
@@ -766,10 +770,14 @@
             return True
 
     def LoadPrevious(self):
-        self.Config, self.ProcessVariables = cPickle.loads(self.Buffer.Previous())
+        config, process_variables = self.Buffer.Previous()
+        self.Config = EtherCATConfigParser.Loads(config)
+        self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
     
     def LoadNext(self):
-        self.Config, self.ProcessVariables = cPickle.loads(self.Buffer.Next())
+        config, process_variables = self.Buffer.Next()
+        self.Config = EtherCATConfigParser.Loads(config)
+        self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
     
     def GetBufferState(self):
         first = self.Buffer.IsFirst()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/entries_list.xslt	Tue Sep 24 00:48:21 2013 +0200
@@ -0,0 +1,123 @@
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:ns="entries_list_ns"
+    extension-element-prefixes="ns"
+    exclude-result-prefixes="ns">
+  <xsl:param name="min_index"/>
+  <xsl:param name="max_index"/>
+  <xsl:template match="Device">
+    <xsl:apply-templates select="Profile/Dictionary/Objects/Object"/>
+    <xsl:for-each select="RxPdo">
+      <xsl:call-template name="pdo_entries">
+        <xsl:with-param name="direction" select="'Receive'"/>
+      </xsl:call-template>
+    </xsl:for-each>
+    <xsl:for-each select="TxPdo">
+      <xsl:call-template name="pdo_entries">
+        <xsl:with-param name="direction" select="'Transmit'"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template match="Object">
+    <xsl:variable name="index">
+      <xsl:value-of select="ns:HexDecValue(Index/text())"/>
+    </xsl:variable>
+    <xsl:variable name="entry_name">
+      <xsl:value-of select="ns:EntryName(Name)"/>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$index &gt;= $min_index and $index &lt;= $max_index">
+        <xsl:variable name="datatype_name">
+          <xsl:value-of select="Type/text()"/>
+        </xsl:variable>
+        <xsl:choose>
+          <xsl:when test="ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]">
+            <xsl:apply-templates select="ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]">
+              <xsl:with-param name="index">
+                <xsl:value-of select="$index"/>
+              </xsl:with-param>
+              <xsl:with-param name="entry_name">
+                <xsl:value-of select="$entry_name"/>
+              </xsl:with-param>
+            </xsl:apply-templates>
+          </xsl:when>
+          <xsl:otherwise>
+            <ns:add_entry>
+              <Index><xsl:value-of select="$index"/></Index>
+              <SubIndex><xsl:text>0</xsl:text></SubIndex>
+              <Name><xsl:value-of select="$entry_name"/></Name>
+              <Type><xsl:value-of select="$datatype_name"/></Type>
+              <BitSize><xsl:value-of select="BitSize/text()"/></BitSize>
+              <Access><xsl:value-of select="Flags/Access/text()"/></Access>
+              <PDOMapping><xsl:value-of select="Flags/PdoMapping/text()"/></PDOMapping>
+            </ns:add_entry>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="DataType">
+    <xsl:param name="index"/>
+    <xsl:param name="entry_name"/>
+    <xsl:for-each select="SubItem">
+      <xsl:variable name="subentry_names">
+        <xsl:value-of select="DisplayName"/>
+        <Default><xsl:value-of select="Name/text()"/></Default>
+      </xsl:variable>
+      <ns:add_entry>
+        <Index><xsl:value-of select="$index"/></Index>
+        <SubIndex><xsl:value-of select="ns:HexDecValue(SubIdx/text())"/></SubIndex>
+        <Name>
+          <xsl:value-of select="$entry_name"/>
+          <xsl:text> - </xsl:text>
+          <xsl:value-of select="ns:EntryName($subentry_names)"/>
+        </Name>
+        <Type><xsl:value-of select="Type/text()"/></Type>
+        <BitSize><xsl:value-of select="BitSize/text()"/></BitSize>
+        <Access><xsl:value-of select="Flags/Access/text()"/></Access>
+        <PDOMapping><xsl:value-of select="Flags/PdoMapping/text()"/></PDOMapping>
+      </ns:add_entry>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template name="pdo_entries">
+    <xsl:param name="direction"/>
+    <xsl:variable name="pdo_index">
+      <xsl:value-of select="ns:HexDecValue(Index/text())"/>
+    </xsl:variable>
+    <xsl:variable name="pdo_name">
+      <xsl:value-of select="ns:EntryName(Name)"/>
+    </xsl:variable>
+    <xsl:for-each select="Entry">
+	  <xsl:variable name="index">
+	    <xsl:value-of select="ns:HexDecValue(Index/text())"/>
+	  </xsl:variable>
+	  <xsl:choose>
+	    <xsl:when test="$index &gt;= $min_index and $index &lt;= $max_index">
+	      <ns:add_entry>
+            <Index><xsl:value-of select="$index"/></Index>
+            <SubIndex><xsl:value-of select="ns:HexDecValue(SubIndex/text())"/></SubIndex>
+            <Name><xsl:value-of select="ns:EntryName(Name)"/></Name>
+            <Type><xsl:value-of select="Type/text()"/></Type>
+            <BitSize><xsl:value-of select="BitLen/text()"/></BitSize>
+            <xsl:choose>
+              <xsl:when test="$direction='Transmit'">
+                <Access><xsl:text>ro</xsl:text></Access>
+                <PDOMapping><xsl:text>T</xsl:text></PDOMapping>
+              </xsl:when>
+              <xsl:otherwise>
+                <Access><xsl:text>wo</xsl:text></Access>
+                <PDOMapping><xsl:text>R</xsl:text></PDOMapping>
+              </xsl:otherwise>
+            </xsl:choose>
+            <PDO>
+              <index><xsl:value-of select="$pdo_index"/></index>
+              <name><xsl:value-of select="$pdo_name"/></name>
+              <type><xsl:value-of select="$direction"/></type>
+            </PDO>
+          </ns:add_entry>
+	    </xsl:when>
+	  </xsl:choose>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template match="text()"/>
+</xsl:stylesheet>
\ No newline at end of file
--- a/etherlab/etherlab.py	Tue Jun 25 00:55:38 2013 +0200
+++ b/etherlab/etherlab.py	Tue Sep 24 00:48:21 2013 +0200
@@ -1,5 +1,5 @@
 import os, shutil
-from xml.dom import minidom
+from lxml import etree
 
 import wx
 import csv
@@ -13,81 +13,79 @@
 from EthercatMaster import _EthercatCTN
 from ConfigEditor import LibraryEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
 
+ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
+
 #--------------------------------------------------
 #                 Ethercat ConfNode
 #--------------------------------------------------
 
-EtherCATInfoClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
-
-cls = EtherCATInfoClasses["EtherCATBase.xsd"].get("DictionaryType", None)
+EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
+EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath)
+
+def extract_param(el):
+    if el.tag == "Index":
+        return "#x%4.4X" % int(el.text)
+    if el.tag == "PDOMapping":
+        if el.text is None:
+            return ""
+        return el.text.upper()
+    if el.text is None:
+        return ""
+    return el.text
+
+def extract_pdo_infos(pdo_infos):
+    return {
+        pdo_infos.tag + " " + el.tag: extract_param(el)
+        for el in pdo_infos}
+
+def HexDecValue(ctxt, values):
+    return str(ExtractHexDecValue(values[0]))
+
+def EntryName(ctxt, values):
+    default=None
+    names = []
+    for element in values:
+        if element.tag == "Default":
+            default = element.text
+        else:
+            names.append(element)
+    return ExtractName(names, default)
+
+class AddEntry(etree.XSLTExtension):
+
+    def __init__(self, entries):
+        etree.XSLTExtension.__init__(self)
+        self.Entries = entries
+    
+    def execute(self, context, self_node, input_node, output_parent):
+        infos = etree.Element('entry_infos')
+        self.process_children(context, infos)
+        index, subindex = map(
+            lambda x: int(infos.find(x).text),
+            ["Index", "SubIndex"])
+        new_entry_infos = {
+            el.tag: extract_param(el)
+            for el in infos if el.tag != "PDO"}
+        if (index, subindex) != (0, 0):
+            entry_infos = self.Entries.get((index, subindex))
+            if entry_infos is not None:
+                PDO_infos = infos.find("PDO")
+                if PDO_infos is not None:
+                    entry_infos.update(extract_pdo_infos(PDO_infos))
+            else:
+                self.Entries[(index, subindex)] = new_entry_infos
+
+entries_list_xslt = etree.parse(
+    os.path.join(ScriptDirectory, "entries_list.xslt"))
+
+cls = EtherCATInfoParser.GetElementClass("DeviceType")
 if cls:
-    cls.loadXMLTreeArgs = None
-    
-    setattr(cls, "_loadXMLTree", getattr(cls, "loadXMLTree"))
-    
-    def loadXMLTree(self, *args):
-        self.loadXMLTreeArgs = args
-    setattr(cls, "loadXMLTree", loadXMLTree)
-
-    def load(self):
-        if self.loadXMLTreeArgs is not None:
-            self._loadXMLTree(*self.loadXMLTreeArgs)
-            self.loadXMLTreeArgs = None
-    setattr(cls, "load", load)
-
-cls = EtherCATInfoClasses["EtherCATInfo.xsd"].get("DeviceType", None)
-if cls:
-    cls.DataTypes = None
-    
+    
+    profile_numbers_xpath = EtherCATInfo_XPath("Profile/ProfileNo")
     def GetProfileNumbers(self):
-        profiles = []
-        
-        for profile in self.getProfile():
-            profile_content = profile.getcontent()
-            if profile_content is None:
-                continue
-            
-            for content_element in profile_content["value"]:
-                if content_element["name"] == "ProfileNo":
-                    profiles.append(content_element["value"])
-        
-        return profiles
+        return [number.text for number in profile_numbers_xpath(self)]
     setattr(cls, "GetProfileNumbers", GetProfileNumbers)
     
-    def GetProfileDictionaries(self):
-        dictionaries = []
-        
-        for profile in self.getProfile():
-        
-            profile_content = profile.getcontent()
-            if profile_content is None:
-                continue
-            
-            for content_element in profile_content["value"]:
-                if content_element["name"] == "Dictionary":
-                    dictionaries.append(content_element["value"])
-                elif content_element["name"] == "DictionaryFile":
-                    raise ValueError, "DictionaryFile for defining Device Profile is not yet supported!"
-                
-        return dictionaries
-    setattr(cls, "GetProfileDictionaries", GetProfileDictionaries)
-    
-    def ExtractDataTypes(self):
-        self.DataTypes = {}
-        
-        for dictionary in self.GetProfileDictionaries():
-            dictionary.load()
-            
-            datatypes = dictionary.getDataTypes()
-            if datatypes is not None:
-                
-                for datatype in datatypes.getDataType():
-                    content = datatype.getcontent()
-                    if content is not None and content["name"] == "SubItem":
-                        self.DataTypes[datatype.getName()] = datatype
-    
-    setattr(cls, "ExtractDataTypes", ExtractDataTypes)
-    
     def getCoE(self):
         mailbox = self.getMailbox()
         if mailbox is not None:
@@ -96,78 +94,22 @@
     setattr(cls, "getCoE", getCoE)
 
     def GetEntriesList(self, limits=None):
-        if self.DataTypes is None:
-            self.ExtractDataTypes()
-        
         entries = {}
         
-        for dictionary in self.GetProfileDictionaries():
-            dictionary.load()
-            
-            for object in dictionary.getObjects().getObject():
-                entry_index = object.getIndex().getcontent()
-                index = ExtractHexDecValue(entry_index)
-                if limits is None or limits[0] <= index <= limits[1]:
-                    entry_type = object.getType()
-                    entry_name = ExtractName(object.getName())
-                    
-                    entry_type_infos = self.DataTypes.get(entry_type, None)
-                    if entry_type_infos is not None:
-                        content = entry_type_infos.getcontent()
-                        for subitem in content["value"]:
-                            entry_subidx = subitem.getSubIdx()
-                            if entry_subidx is None:
-                                entry_subidx = "0"
-                            subidx = ExtractHexDecValue(entry_subidx)
-                            subitem_access = ""
-                            subitem_pdomapping = ""
-                            subitem_flags = subitem.getFlags()
-                            if subitem_flags is not None:
-                                access = subitem_flags.getAccess()
-                                if access is not None:
-                                    subitem_access = access.getcontent()
-                                pdomapping = subitem_flags.getPdoMapping()
-                                if pdomapping is not None:
-                                    subitem_pdomapping = pdomapping.upper()
-                            entries[(index, subidx)] = {
-                                "Index": entry_index,
-                                "SubIndex": entry_subidx,
-                                "Name": "%s - %s" % 
-                                        (entry_name.decode("utf-8"),
-                                         ExtractName(subitem.getDisplayName(), 
-                                                     subitem.getName()).decode("utf-8")),
-                                "Type": subitem.getType(),
-                                "BitSize": subitem.getBitSize(),
-                                "Access": subitem_access, 
-                                "PDOMapping": subitem_pdomapping}
-                    else:
-                        entry_access = ""
-                        entry_pdomapping = ""
-                        entry_flags = object.getFlags()
-                        if entry_flags is not None:
-                            access = entry_flags.getAccess()
-                            if access is not None:
-                                entry_access = access.getcontent()
-                            pdomapping = entry_flags.getPdoMapping()
-                            if pdomapping is not None:
-                                entry_pdomapping = pdomapping.upper()
-                        entries[(index, 0)] = {
-                             "Index": entry_index,
-                             "SubIndex": "0",
-                             "Name": entry_name,
-                             "Type": entry_type,
-                             "BitSize": object.getBitSize(),
-                             "Access": entry_access,
-                             "PDOMapping": entry_pdomapping}
-
-        for TxPdo in self.getTxPdo():
-            ExtractPdoInfos(TxPdo, "Transmit", entries, limits)
-        for RxPdo in self.getRxPdo():
-            ExtractPdoInfos(RxPdo, "Receive", entries, limits)
+        entries_list_xslt_tree = etree.XSLT(
+            entries_list_xslt, extensions = {
+                ("entries_list_ns", "add_entry"): AddEntry(entries),
+                ("entries_list_ns", "HexDecValue"): HexDecValue,
+                ("entries_list_ns", "EntryName"): EntryName})
+        entries_list_xslt_tree(self, **dict(zip(
+            ["min_index", "max_index"], 
+            map(lambda x: etree.XSLT.strparam(str(x)),
+                limits if limits is not None else [0x0000, 0xFFFF])
+            )))
         
         return entries
     setattr(cls, "GetEntriesList", GetEntriesList)
-    
+
     def GetSyncManagers(self):
         sync_managers = []
         for sync_manager in self.getSm():
@@ -200,38 +142,6 @@
             SortGroupItems(item)
     group["children"].sort(GroupItemCompare)
 
-def ExtractPdoInfos(pdo, pdo_type, entries, limits=None):
-    pdo_index = pdo.getIndex().getcontent()
-    pdo_name = ExtractName(pdo.getName())
-    for pdo_entry in pdo.getEntry():
-        entry_index = pdo_entry.getIndex().getcontent()
-        entry_subindex = pdo_entry.getSubIndex()
-        index = ExtractHexDecValue(entry_index)
-        subindex = ExtractHexDecValue(entry_subindex)
-        
-        if limits is None or limits[0] <= index <= limits[1]:
-            entry = entries.get((index, subindex), None)
-            if entry is not None:
-                entry["PDO index"] = pdo_index
-                entry["PDO name"] = pdo_name
-                entry["PDO type"] = pdo_type
-            else:
-                entry_type = pdo_entry.getDataType()
-                if entry_type is not None:
-                    if pdo_type == "Transmit":
-                        access = "ro"
-                        pdomapping = "T"
-                    else:
-                        access = "wo"
-                        pdomapping = "R"
-                    entries[(index, subindex)] = {
-                        "Index": entry_index,
-                        "SubIndex": entry_subindex,
-                        "Name": ExtractName(pdo_entry.getName()),
-                        "Type": entry_type.getcontent(),
-                        "Access": access,
-                        "PDOMapping": pdomapping}
-
 class ModulesLibrary:
 
     MODULES_EXTRA_PARAMS = [
@@ -276,6 +186,8 @@
     def GetModulesExtraParamsFilePath(self):
         return os.path.join(self.Path, "modules_extra_params.cfg")
     
+    groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group")
+    devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device")
     def LoadModules(self):
         self.Library = {}
         
@@ -283,37 +195,40 @@
         for file in files:
             filepath = os.path.join(self.Path, file)
             if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml":
+                self.modules_infos = None
+                
                 xmlfile = open(filepath, 'r')
-                xml_tree = minidom.parse(xmlfile)
+                try:
+                    self.modules_infos = etree.fromstring(
+                        xmlfile.read(), EtherCATInfoParser)
+                except:
+                    pass
                 xmlfile.close()
                 
-                self.modules_infos = None
-                for child in xml_tree.childNodes:
-                    if child.nodeType == xml_tree.ELEMENT_NODE and child.nodeName == "EtherCATInfo":
-                        self.modules_infos = EtherCATInfoClasses["EtherCATInfo.xsd"]["EtherCATInfo"]()
-                        self.modules_infos.loadXMLTree(child)
-                
                 if self.modules_infos is not None:
                     vendor = self.modules_infos.getVendor()
                     
-                    vendor_category = self.Library.setdefault(ExtractHexDecValue(vendor.getId()), 
-                                                              {"name": ExtractName(vendor.getName(), _("Miscellaneous")), 
-                                                               "groups": {}})
+                    vendor_category = self.Library.setdefault(
+                        ExtractHexDecValue(vendor.getId()), 
+                        {"name": ExtractName(vendor.getName(), _("Miscellaneous")), 
+                         "groups": {}})
                     
-                    for group in self.modules_infos.getDescriptions().getGroups().getGroup():
+                    for group in self.groups_xpath(self.modules_infos):
                         group_type = group.getType()
                         
-                        vendor_category["groups"].setdefault(group_type, {"name": ExtractName(group.getName(), group_type), 
-                                                                          "parent": group.getParentGroup(),
-                                                                          "order": group.getSortOrder(), 
-                                                                          "value": group.getcontent()["value"],
-                                                                          "devices": []})
+                        vendor_category["groups"].setdefault(group_type, 
+                            {"name": ExtractName(group.getName(), group_type), 
+                             "parent": group.getParentGroup(),
+                             "order": group.getSortOrder(), 
+                             #"value": group.getcontent()["value"],
+                             "devices": []})
                     
-                    for device in self.modules_infos.getDescriptions().getDevices().getDevice():
+                    for device in self.devices_xpath(self.modules_infos):
                         device_group = device.getGroupType()
                         if not vendor_category["groups"].has_key(device_group):
                             raise ValueError, "Not such group \"%\"" % device_group
-                        vendor_category["groups"][device_group]["devices"].append((device.getType().getcontent(), device))
+                        vendor_category["groups"][device_group]["devices"].append(
+                            (device.getType().getcontent(), device))
 
         return self.Library 
 
@@ -464,8 +379,8 @@
     
     CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")]
     EditorType = LibraryEditor
-       
-    
+       
+    
     def __init__(self):
         self.ModulesLibrary = None
         self.LoadModulesLibrary()