PLCControler.py
changeset 125 394d9f168258
parent 121 40b91ba978db
child 128 d16a8df4d322
--- a/PLCControler.py	Tue Nov 27 12:58:34 2007 +0100
+++ b/PLCControler.py	Thu Dec 06 18:05:29 2007 +0100
@@ -37,7 +37,10 @@
 duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:.[0-9]*)?)ms)?")
 
 [ITEM_UNEDITABLE, ITEM_PROJECT, ITEM_POU, ITEM_CLASS, ITEM_VARIABLE,
- ITEM_TRANSITION, ITEM_ACTION, ITEM_CONFIGURATION, ITEM_RESOURCE] = range(9)
+ ITEM_TRANSITION, ITEM_ACTION, ITEM_CONFIGURATION, ITEM_RESOURCE, 
+ ITEM_DATATYPE] = range(10)
+
+ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
 
 """
 pyxsval is not complete and the parts that are not supported print some error
@@ -167,6 +170,8 @@
         self.FilePath = ""
         self.FileName = ""
         self.ProgramFilePath = ""
+        self.RefreshDataTypeUsingTree()
+        self.RefreshDataTypes()
         self.RefreshPouUsingTree()
         self.RefreshBlockTypes()
 
@@ -192,6 +197,12 @@
         self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), False)
         self.Buffering = False
     
+    # Return project data type names
+    def GetProjectDataTypeNames(self):
+        if self.Project:
+            return [datatype.getName() for datatype in self.Project.getDataTypes()]
+        return []
+    
     # Return project pou names
     def GetProjectPouNames(self):
         if self.Project:
@@ -263,6 +274,9 @@
     def GetProjectInfos(self):
         if self.Project:
             infos = {"name": self.Project.getName(), "type": ITEM_PROJECT}
+            datatypes = {"name": "Data Types", "type": ITEM_UNEDITABLE, "values":[]}
+            for datatype in self.Project.getDataTypes():
+                datatypes["values"].append({"name": datatype.getName(), "type": ITEM_DATATYPE, "values": []})
             pou_types = {"function": {"name": "Functions", "type": ITEM_UNEDITABLE, "values":[]},
                          "functionBlock": {"name": "Function Blocks", "type": ITEM_UNEDITABLE, "values":[]},
                          "program": {"name": "Programs", "type": ITEM_UNEDITABLE, "values":[]}}
@@ -294,11 +308,38 @@
                 config_infos["values"] = [resources]
                 configurations["values"].append(config_infos)
             infos["values"] = [{"name": "Properties", "type": ITEM_UNEDITABLE, "values": []},
-                               pou_types["function"], pou_types["functionBlock"], 
+                               datatypes, pou_types["function"], pou_types["functionBlock"], 
                                pou_types["program"], configurations]
             return infos
         return None
 
+    # Refresh the tree of user-defined data type cross-use
+    def RefreshDataTypeUsingTree(self):
+        # Reset the tree of user-defined pou cross-use
+        self.DataTypeUsingTree = {}
+        if self.Project:
+            datatypes = self.Project.getDataTypes()
+            # Reference all the user-defined data type names and initialize the tree of 
+            # user-defined data type cross-use
+            datatypenames = [datatype.getName() for datatype in datatypes]
+            for name in datatypenames:
+                self.DataTypeUsingTree[name] = []
+            # Analyze each data type
+            for datatype in datatypes:
+                name = datatype.getName()
+                basetype_content = datatype.getBaseType().getContent()
+                if basetype_content["value"] is not None:
+                    if basetype_content["name"] == "derived":
+                        basetype_name = basetype_content["value"].getName()
+                        if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]:
+                            self.DataTypeUsingTree[basetype_name].append(name)
+                    elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
+                        base_type = basetype_content["value"].baseType.getContent()
+                        if base_type["value"] is not None:
+                            basetype_name = base_type["value"].getName()
+                            if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]:
+                                self.DataTypeUsingTree[basetype_name].append(name)
+    
     # Refresh the tree of user-defined pou cross-use
     def RefreshPouUsingTree(self):
         # Reset the tree of user-defined pou cross-use
@@ -317,9 +358,9 @@
                     # Extract variables from every varLists
                     for type, varlist in pou.getVars():
                         for var in varlist.getVariable():
-                            var_type = var.getType().getValue()
-                            if not isinstance(var_type, (StringType, UnicodeType)):
-                                typename = var_type.getName()
+                            vartype_content = var.getType().getContent()
+                            if vartype_content["value"] is not None:
+                                typename = vartype_content["value"].getName()
                                 if typename in pounames and name not in self.PouUsingTree[typename]:
                                     self.PouUsingTree[typename].append(name)
                 bodytype = pou.getBodyType()
@@ -342,12 +383,34 @@
                         if typename != name and typename_model.search(text):
                             self.PouUsingTree[typename].append(name)
 
+    # Return if data type given by name is used by another data type or pou
+    def DataTypeIsUsed(self, name):
+        if name in self.DataTypeUsingTree:
+            return len(self.DataTypeUsingTree[name]) > 0
+        return False
+
     # Return if pou given by name is used by another pou
     def PouIsUsed(self, name):
         if name in self.PouUsingTree:
             return len(self.PouUsingTree[name]) > 0
         return False
 
+    # Return if data type given by name is directly or undirectly used by the reference data type
+    def DataTypeIsUsedBy(self, name, reference):
+        if name in self.DataTypeUsingTree:
+            list = self.DataTypeUsingTree[name]
+            # Test if data type is directly used by reference
+            if reference in list:
+                return True
+            else:
+                # Test if data type is undirectly used by reference, by testing if data types 
+                # that directly use data type is directly or undirectly used by reference
+                used = False
+                for element in list:
+                    used |= self.DataTypeIsUsedBy(element, reference)
+                return used
+        return False
+
     # Return if pou given by name is directly or undirectly used by the reference pou
     def PouIsUsedBy(self, name, reference):
         if name in self.PouUsingTree:
@@ -380,7 +443,22 @@
 #-------------------------------------------------------------------------------
 #                        Project Pous management functions
 #-------------------------------------------------------------------------------
-        
+    
+    # Add a Data Type to Project
+    def ProjectAddDataType(self, datatype_name):
+        # Add the pou to project
+        self.Project.appendDataType(datatype_name)
+        self.RefreshDataTypeUsingTree()
+        self.RefreshDataTypes()
+        self.BufferProject()
+    
+    # Remove a Data Type from project
+    def ProjectRemoveDataType(self, datatype_name):
+        self.Project.removeDataType(datatype_name)
+        self.RefreshDataTypeUsingTree()
+        self.RefreshDataTypes()
+        self.BufferProject()
+    
     # Add a Pou to Project
     def ProjectAddPou(self, pou_name, pou_type, body_type):
         # Add the pou to project
@@ -391,7 +469,7 @@
         self.RefreshBlockTypes()
         self.BufferProject()
     
-    # Remove a pou from project
+    # Remove a Pou from project
     def ProjectRemovePou(self, pou_name):
         self.Project.removePou(pou_name)
         self.RefreshPouUsingTree()
@@ -401,8 +479,6 @@
     # Add a configuration to Project
     def ProjectAddConfiguration(self, config_name):
         self.Project.addConfiguration(config_name)
-        self.RefreshPouUsingTree()
-        self.RefreshBlockTypes()
         self.BufferProject()
     
     # Remove a configuration from project
@@ -413,8 +489,6 @@
     # Add a resource to a configuration of the Project
     def ProjectAddConfigurationResource(self, config_name, resource_name):
         self.Project.addConfigurationResource(config_name, resource_name)
-        self.RefreshPouUsingTree()
-        self.RefreshBlockTypes()
         self.BufferProject()
     
     # Remove a resource from a configuration of the project
@@ -450,7 +524,15 @@
         pou = self.Project.getPou(pou_name)
         pou.removeAction(action_name)
         self.BufferProject()
-        
+    
+    # Change the name of a pou
+    def ChangeDataTypeName(self, old_name, new_name):
+        # Found the pou corresponding to old name and change its name to new name
+        datatype = self.Project.getDataType(old_name)
+        datatype.setName(new_name)
+        self.Project.updateElementName(old_name, new_name)
+        self.BufferProject()
+    
     # Change the name of a pou
     def ChangePouName(self, old_name, new_name):
         # Found the pou corresponding to old name and change its name to new name
@@ -575,12 +657,12 @@
             tempvar = plcopen.varListPlain_variable()
             tempvar.setName(var["Name"])
             var_type = plcopen.dataType()
-            if GetBlockType(var["Type"]) != None:
+            if var["Type"] not in var_type.getChoices():
                 derived_type = plcopen.derived()
                 derived_type.setName(var["Type"])
-                var_type.setValue(derived_type)
+                var_type.setContent("derived", derived_type)
             else:
-                var_type.setValue(var["Type"])
+                var_type.setContent(var["Type"], None)
             tempvar.setType(var_type)
             if var["Initial Value"] != "":
                 value = plcopen.value()
@@ -615,11 +697,11 @@
             for varlist in configuration.getGlobalVars():
                 for var in varlist.getVariable():
                     tempvar = {"Name":var.getName(),"Class":"Global"}
-                    var_type = var.getType().getValue()
-                    if isinstance(var_type, (StringType, UnicodeType)):
-                        tempvar["Type"] = var_type
+                    vartype_content = var.getType().getContent()
+                    if vartype_content["value"] is None:
+                        tempvar["Type"] = vartype_content["name"]
                     else:
-                        tempvar["Type"] = var_type.getName()
+                        tempvar["Type"] = vartype_content["value"].getName()
                     tempvar["Edit"] = True
                     initial = var.getInitialValue()
                     if initial:
@@ -663,11 +745,11 @@
             for varlist in resource.getGlobalVars():
                 for var in varlist.getVariable():
                     tempvar = {"Name":var.getName(),"Class":"Global"}
-                    var_type = var.getType().getValue()
-                    if isinstance(var_type, (StringType, UnicodeType)):
-                        tempvar["Type"] = var_type
+                    vartype_content = var.getType().getContent()
+                    if vartype_content["value"] is None:
+                        tempvar["Type"] = vartype_content["name"]
                     else:
-                        tempvar["Type"] = var_type.getName()
+                        tempvar["Type"] = vartype_content["value"].getName()
                     tempvar["Edit"] = True
                     initial = var.getInitialValue()
                     if initial:
@@ -704,12 +786,12 @@
             for type, varlist in pou.getVars():
                 for var in varlist.getVariable():
                     tempvar = {"Name":var.getName(),"Class":type}
-                    var_type = var.getType().getValue()
-                    if isinstance(var_type, (StringType, UnicodeType)):
-                        tempvar["Type"] = var_type
+                    vartype_content = var.getType().getContent()
+                    if vartype_content["value"] is None:
+                        tempvar["Type"] = vartype_content["name"]
                         tempvar["Edit"] = True
                     else:
-                        tempvar["Type"] = var_type.getName()
+                        tempvar["Type"] = vartype_content["value"].getName()
                         tempvar["Edit"] = not pou.hasBlock(tempvar["Name"])
                     initial = var.getInitialValue()
                     if initial:
@@ -754,7 +836,12 @@
             return_type = plcopen.dataType()
             pou.interface.setReturnType(return_type)
         # Change return type
-        return_type.setValue(type)
+        if type in self.GetBaseTypes():
+            return_type.setContent(type, None)
+        else:
+            derived_type = plcopen.derived()
+            derived_type.setName(type)
+            return_type.setContent("derived", derived_type)
         self.RefreshBlockTypes()
     
     def UpdateProjectUsedPous(self, old_name, new_name):
@@ -778,9 +865,39 @@
             # Return the return type if there is one
             return_type = pou.interface.getReturnType()
             if return_type:
-                return return_type.getValue()
+                returntype_content = return_type.getContent()
+                if returntype_content["value"] is None:
+                    return returntype_content["name"]
+                else:
+                    return returntype_content["value"].getName()
         return None
-
+    
+    # Update data types with user-defined data types added
+    def RefreshDataTypes(self):
+        ResetTypeHierarchy()
+        ResetEnumeratedDataValues()
+        if self.Project:
+            for datatype in self.Project.getDataTypes():
+                name = datatype.getName()
+                basetype_content = datatype.getBaseType().getContent()
+                if basetype_content["value"] is None:
+                    AddDataTypeHierarchy(name, basetype_content["name"])
+                elif basetype_content["name"] == "derived":
+                    AddDataTypeHierarchy(name, basetype_content["value"].getName())
+                elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
+                    base_type = basetype_content["value"].baseType.getContent()
+                    if base_type["value"] is None:
+                        AddDataTypeHierarchy(name, base_type["name"])
+                    else:
+                        AddDataTypeHierarchy(name, base_type["value"].getName())
+                else:
+                    if basetype_content["name"] == "enum":
+                        values = []
+                        for value in basetype_content["value"].values.getValue():
+                            values.append(value.getName())
+                        AddEnumeratedDataValues(values)
+                    AddDataTypeHierarchy(name, "ANY_DERIVED")
+    
     # Update Block types with user-defined pou added
     def RefreshBlockTypes(self):
         if BlockTypes[-1]["name"] == "User-defined POUs":
@@ -799,17 +916,34 @@
                         for type, varlist in pou.getVars():
                             if type == "InOut":
                                 for var in varlist.getVariable():
-                                    block_infos["inputs"].append((var.getName(),var.getType().getValue(),"none"))
-                                    block_infos["outputs"].append((var.getName(),var.getType().getValue(),"none"))
+                                    var_type = var.type.getContent()
+                                    if var_type["value"] is None:
+                                        block_infos["inputs"].append((var.getName(),var_type["name"],"none"))
+                                        block_infos["outputs"].append((var.getName(),var_type["name"],"none"))
+                                    else:
+                                        block_infos["inputs"].append((var.getName(),var_type["value"].getName(),"none"))
+                                        block_infos["outputs"].append((var.getName(),var_type["value"].getName(),"none"))
                             elif type == "Input":
                                 for var in varlist.getVariable():
-                                    block_infos["inputs"].append((var.getName(),var.getType().getValue(),"none"))
+                                    var_type = var.type.getContent()
+                                    if var_type["value"] is None:
+                                        block_infos["inputs"].append((var.getName(),var_type["name"],"none"))
+                                    else:
+                                        block_infos["inputs"].append((var.getName(),var_type["value"].getName(),"none"))
                             elif type == "Output":
                                 for var in varlist.getVariable():
-                                    block_infos["outputs"].append((var.getName(),var.getType().getValue(),"none"))
+                                    var_type = var.type.getContent()
+                                    if var_type["value"] is None:
+                                        block_infos["outputs"].append((var.getName(),var_type["name"],"none"))
+                                    else:
+                                        block_infos["outputs"].append((var.getName(),var_type["value"].getName(),"none"))
                         return_type = pou.interface.getReturnType()
                         if return_type:
-                            block_infos["outputs"].append(("",return_type.getValue(),"none"))
+                            var_type = return_type.getContent()
+                            if var_type["value"] is None:
+                                block_infos["outputs"].append(("",var_type["name"],"none"))
+                            else:
+                                block_infos["outputs"].append(("",var_type["value"].getName(),"none"))
                     if pou.getBodyType() in ["FBD","LD","SFC"]:
                         for instance in pou.getInstances():
                             if isinstance(instance, plcopen.comment):
@@ -818,16 +952,13 @@
     
     # Return Block types checking for recursion
     def GetBlockTypes(self, tagname = ""):
+        name = ""
+        type = None
         if self.Project:
             words = tagname.split("::")
-            if len(words) == 1:
-                name = current_name
-            else:
+            if words[0] in ["P","T","A"]:
                 name = words[1]
-            type = self.GetPouType(name)
-        else:
-            name = ""
-            type = None
+                type = self.GetPouType(name)
         if type == "function":
             blocktypes = []
             for category in BlockTypes[:-1] + PluginTypes:
@@ -853,10 +984,7 @@
         if self.Project:
             words = tagname.split("::")
             if words[0] in ["P","T","A"]:
-                if len(words) == 1:
-                    name = current_name
-                else:
-                    name = words[1]
+                name = words[1]
                 type = self.GetPouType(name)
         blocktypes = []
         for category in BlockTypes[:-1]:
@@ -882,11 +1010,45 @@
                     blocktypes.append(pou.getName())
         return blocktypes
 
+    # Return Data Types checking for recursion
+    def GetDataTypes(self, tagname = "", basetypes = True):
+        if basetypes:
+            datatypes = self.GetBaseTypes()
+        else:
+            datatypes = []
+        if self.Project:
+            words = tagname.split("::")
+            if words[0] in ["D"]:
+                name = words[1]
+            else:
+                name = ""
+            for datatype in self.Project.getDataTypes():
+                datatype_name = datatype.getName()
+                if datatype_name != name and not self.DataTypeIsUsedBy(name, datatype_name):
+                    datatypes.append(datatype_name)
+        return datatypes
+
+    # Return Base Types
+    def GetBaseTypes(self):
+        return [value for value, parent in TypeHierarchy_list if not value.startswith("ANY")]
+
+    # Return Subrange types
+    def GetSubrangeTypes(self):
+        return [value for value, range in DataTypeRange_list]
+
+    # Return Enumerated Values
+    def GetEnumeratedDataValues(self):
+        return EnumeratedDataValues
+
 #-------------------------------------------------------------------------------
 #                   Project Element tag name computation functions
 #-------------------------------------------------------------------------------
     
-    # Compute a pou transition name
+    # Compute a data type name
+    def ComputeDataTypeName(self, datatype):
+        return "D::%s" % datatype
+    
+    # Compute a pou name
     def ComputePouName(self, pou):
         return "P::%s" % pou
     
@@ -905,6 +1067,112 @@
     # Compute a pou  name
     def ComputeConfigurationResourceName(self, config, resource):
         return "R::%s::%s" % (config, resource)
+
+#-------------------------------------------------------------------------------
+#                    Project opened Data types management functions
+#-------------------------------------------------------------------------------
+
+    # Return the data type informations
+    def GetDataTypeInfos(self, tagname):
+        words = tagname.split("::")
+        if words[0] == "D":
+            infos = {}
+            datatype = self.Project.getDataType(words[1])
+            basetype_content = datatype.baseType.getContent()
+            if basetype_content["value"] is None:
+                infos["type"] = "Directly"
+                infos["base_type"] = basetype_content["name"]
+            elif basetype_content["name"] == "derived":
+                infos["type"] = "Directly"
+                infos["base_type"] = basetype_content["value"].getName()
+            elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
+                infos["type"] = "Subrange"
+                infos["min"] = basetype_content["value"].range.getLower()
+                infos["max"] = basetype_content["value"].range.getUpper()
+                base_type = basetype_content["value"].baseType.getContent()
+                if base_type["value"] is None:
+                    infos["base_type"] = base_type["name"]
+                else:
+                    infos["base_type"] = base_type["value"].getName()
+            elif basetype_content["name"] == "enum":
+                infos["type"] = "Enumerated"
+                infos["values"] = []
+                for value in basetype_content["value"].values.getValue():
+                    infos["values"].append(value.getName())
+            elif basetype_content["name"] == "array":
+                infos["type"] = "Array"
+                infos["dimensions"] = []
+                for dimension in basetype_content["value"].getDimension():
+                    infos["dimensions"].append(str(dimension.getUpper()))
+                base_type = basetype_content["value"].baseType.getContent()
+                if base_type["value"] is None:
+                    infos["base_type"] = base_type["name"]
+                else:
+                    infos["base_type"] = base_type["value"].getName()
+            if datatype.initialValue is not None:
+                infos["initial"] = str(datatype.initialValue.getValue())
+            else:
+                infos["initial"] = ""
+            return infos
+        return None
+    
+    # Change the data type informations
+    def SetDataTypeInfos(self, tagname, infos):
+        words = tagname.split("::")
+        if words[0] == "D":
+            datatype = self.Project.getDataType(words[1])
+            if infos["type"] == "Directly":
+                if infos["base_type"] in self.GetBaseTypes():
+                    datatype.baseType.setContent(infos["base_type"], None)
+                else:
+                    derived_datatype = plcopen.derived()
+                    derived_datatype.setName(infos["base_type"])
+                    datatype.baseType.setContent("derived", derived_datatype)
+            elif infos["type"] == "Subrange":
+                if infos["base_type"] in GetSubTypes("ANY_UINT"):
+                    subrange = plcopen.subrangeUnsigned()
+                    datatype.baseType.setContent("subrangeUnsigned", subrange)
+                else:
+                    subrange = plcopen.subrangeSigned()
+                    datatype.baseType.setContent("subrangeSigned", subrange)
+                subrange.range.setLower(infos["min"])
+                subrange.range.setUpper(infos["max"])
+                if infos["base_type"] in self.GetBaseTypes():
+                    subrange.baseType.setContent(infos["base_type"], None)
+                else:
+                    derived_datatype = plcopen.derived()
+                    derived_datatype.setName(infos["base_type"])
+                    subrange.baseType.setContent("derived", derived_datatype)
+            elif infos["type"] == "Enumerated":
+                enumerated = plcopen.enum()
+                for enum_value in infos["values"]:
+                    value = plcopen.values_value()
+                    value.setName(enum_value)
+                    enumerated.values.appendValue(value)
+                datatype.baseType.setContent("enum", enumerated)
+            elif infos["type"] == "Array":
+                array = plcopen.array()
+                for dimension in infos["dimensions"]:
+                    dimension_range = plcopen.rangeSigned()
+                    dimension_range.setLower(1)
+                    dimension_range.setUpper(int(dimension))
+                    array.appendDimension(dimension_range)
+                if infos["base_type"] in self.GetBaseTypes():
+                    array.baseType.setContent(infos["base_type"], None)
+                else:
+                    derived_datatype = plcopen.derived()
+                    derived_datatype.setName(infos["base_type"])
+                    array.baseType.setContent("derived", derived_datatype)
+                datatype.baseType.setContent("array", array)
+            if infos["initial"] != "":
+                if datatype.initialValue is None:
+                    datatype.initialValue = plcopen.value()
+                datatype.initialValue.setValue(infos["initial"])
+            else:
+                datatype.initialValue = None
+            self.RefreshDataTypeUsingTree()
+            self.RefreshDataTypes()
+            self.BufferProject()
     
 #-------------------------------------------------------------------------------
 #                       Project opened Pous management functions
@@ -972,7 +1240,7 @@
             return "BOOL"
         return None
     
-    # Change the edited element taxt
+    # Change the edited element text
     def SetEditedElementText(self, tagname, text):
         element = self.GetEditedElement(tagname)
         if element != None:
@@ -1331,7 +1599,11 @@
             for type, varlist in pou.getVars():
                 for var in varlist.getVariable():
                     if var.getName() == varname:
-                        return var.getType().getValue()
+                        vartype_content = var.getType().getContent()
+                        if vartype_content["value"] is None:
+                            return vartype_content["name"]
+                        else:
+                            return vartype_content["value"].getName()
         return None
     
     def SetConnectionWires(self, connection, connector):
@@ -1998,7 +2270,7 @@
         if self.VerifyXML:
             if sys:
                 sys.stdout = HolePseudoFile()
-            result = pyxsval.parseAndValidate(filepath, os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd"))
+            result = pyxsval.parseAndValidate(filepath, os.path.join(ScriptDirectory, "plcopen", "TC6_XML_V10_B.xsd"))
             if sys:
                 sys.stdout = sys.__stdout__
             tree = result.getTree()
@@ -2016,6 +2288,8 @@
                 self.Buffering = False
                 self.ElementsOpened = []
                 self.CurrentElementEditing = None
+                self.RefreshDataTypeUsingTree()
+                self.RefreshDataTypes()
                 self.RefreshPouUsingTree()
                 self.RefreshBlockTypes()
                 return None
@@ -2031,11 +2305,11 @@
                       "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
                       "xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd http://www.plcopen.org/xml/tc6.xsd"}
             text += self.Project.generateXMLText("project", 0, extras)
-
+            
             if self.VerifyXML:
                 if sys:
                     sys.stdout = HolePseudoFile()
-                pyxsval.parseAndValidateString(text, open(os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd"),"r").read())
+                pyxsval.parseAndValidateString(text, open(os.path.join(ScriptDirectory, "plcopen", "TC6_XML_V10_B.xsd"),"r").read())
                 if sys:
                     sys.stdout = sys.__stdout__