Replaced old pou instance type tagname computing by xslt stylesheet
authorLaurent Bessard
Mon, 23 Sep 2013 00:32:39 +0200
changeset 1321 83f41ea00b97
parent 1320 bb04c41cbee9
child 1322 0a9227f743b3
Replaced old pou instance type tagname computing by xslt stylesheet
PLCControler.py
plcopen/instance_tagname.xslt
--- a/PLCControler.py	Wed Sep 18 15:31:38 2013 +0200
+++ b/PLCControler.py	Mon Sep 23 00:32:39 2013 +0200
@@ -279,6 +279,57 @@
     os.path.join(ScriptDirectory, "plcopen", "instances_path.xslt"))
 
 #-------------------------------------------------------------------------------
+#            Helpers object for generating instance tagname
+#-------------------------------------------------------------------------------
+
+class InstanceTagName(etree.XSLTExtension):
+
+    def __init__(self, controller):
+        etree.XSLTExtension.__init__(self)
+        self.Controller = controller
+    
+    def GetTagName(self, infos):
+        return ""
+    
+    def execute(self, context, self_node, input_node, output_parent):
+        tagname_infos = etree.Element('infos')
+        self.process_children(context, tagname_infos)
+        tagname = etree.Element('tagname')
+        tagname.text = self.GetTagName(tagname_infos)
+        output_parent.append(tagname)
+
+class ConfigTagName(InstanceTagName):
+    
+    def GetTagName(self, infos):
+        return self.Controller.ComputeConfigurationName(infos.get("name"))
+        
+class ResourceTagName(InstanceTagName):
+    
+    def GetTagName(self, infos):
+        return self.Controller.ComputeConfigurationResourceName(
+            infos.get("config_name"), infos.get("name"))
+
+class PouTagName(InstanceTagName):
+    
+    def GetTagName(self, infos):
+        return self.Controller.ComputePouName(infos.get("name"))
+
+class ActionTagName(InstanceTagName):
+    
+    def GetTagName(self, infos):
+        return self.Controller.ComputePouActionName(
+            infos.get("pou_name"), infos.get("name"))
+
+class TransitionTagName(InstanceTagName):
+    
+    def GetTagName(self, infos):
+        return self.Controller.ComputePouTransitionName(
+            infos.get("pou_name"), infos.get("name"))
+
+instance_tagname_xslt = etree.parse(
+    os.path.join(ScriptDirectory, "plcopen", "instance_tagname.xslt"))
+
+#-------------------------------------------------------------------------------
 #                         Undo Buffer for PLCOpenEditor
 #-------------------------------------------------------------------------------
 
@@ -587,7 +638,7 @@
             if obj is not None:
                 return compute_instance_tree(
                         pou_variable_xslt_tree(obj).getroot())
-        return []
+        return None
 
     def GetInstanceList(self, root, name, debug = False):
         project = self.GetProject(debug)
@@ -621,99 +672,24 @@
                             self.ComputePouName(words[1]), debug)]
         return []
     
-    def RecursiveGetPouInstanceTagName(self, project, pou_type, parts, debug = False):
-        pou = project.getpou(pou_type)
-        if pou is not None:
-            if len(parts) == 0:
-                return self.ComputePouName(pou_type)
-            
-            for varlist_type, varlist in pou.getvars():
-                for variable in varlist.getvariable():
-                    if variable.getname() == parts[0]:
-                        vartype_content = variable.gettype().getcontent()
-                        if vartype_content.getLocalTag() == "derived":
-                            return self.RecursiveGetPouInstanceTagName(
-                                            project, 
-                                            vartype_content.getname(),
-                                            parts[1:], debug)
-            
-            if pou.getbodyType() == "SFC" and len(parts) == 1:
-                for action in pou.getactionList():
-                    if action.getname() == parts[0]:
-                        return self.ComputePouActionName(pou_type, parts[0])
-                for transition in pou.gettransitionList():
-                    if transition.getname() == parts[0]:
-                        return self.ComputePouTransitionName(pou_type, parts[0])
-        else:
-            block_infos = self.GetBlockType(pou_type, debug=debug)
-            if (block_infos is not None and 
-                block_infos["type"] in ["program", "functionBlock"]):
-                
-                if len(parts) == 0:
-                    return self.ComputePouName(pou_type)
-                
-                for varname, vartype, varmodifier in block_infos["inputs"] + block_infos["outputs"]:
-                    if varname == parts[0]:
-                        return self.RecursiveGetPouInstanceTagName(project, vartype, parts[1:], debug)
-        return None
-    
-    def GetGlobalInstanceTagName(self, project, element, parts, debug = False):
-        for varlist in element.getglobalVars():
-            for variable in varlist.getvariable():
-                if variable.getname() == parts[0]:
-                    vartype_content = variable.gettype().getcontent()
-                    if vartype_content.getLocalTag() == "derived":                        
-                        if len(parts) == 1:
-                            return self.ComputePouName(
-                                        vartype_content.getname())
-                        else:
-                            return self.RecursiveGetPouInstanceTagName(
-                                        project, 
-                                        vartype_content.getname(),
-                                        parts[1:], debug)
-        return None
-    
     def GetPouInstanceTagName(self, instance_path, debug = False):
         project = self.GetProject(debug)
-        parts = instance_path.split(".")
-        if len(parts) == 1:
-            return self.ComputeConfigurationName(parts[0])
-        elif len(parts) == 2:
-            for config in project.getconfigurations():
-                if config.getname() == parts[0]:
-                    result = self.GetGlobalInstanceTagName(project, 
-                                                           config, 
-                                                           parts[1:],
-                                                           debug)
-                    if result is not None:
-                        return result
-            return self.ComputeConfigurationResourceName(parts[0], parts[1])
-        else:
-            for config in project.getconfigurations():
-                if config.getname() == parts[0]:
-                    for resource in config.getresource():
-                        if resource.getname() == parts[1]:
-                            pou_instances = resource.getpouInstance()[:]
-                            for task in resource.gettask():
-                                pou_instances.extend(task.getpouInstance())
-                            for pou_instance in pou_instances:
-                                if pou_instance.getname() == parts[2]:
-                                    if len(parts) == 3:
-                                        return self.ComputePouName(
-                                                    pou_instance.gettypeName())
-                                    else:
-                                        return self.RecursiveGetPouInstanceTagName(
-                                                    project,
-                                                    pou_instance.gettypeName(),
-                                                    parts[3:], debug)
-                            return self.GetGlobalInstanceTagName(project, 
-                                                                 resource, 
-                                                                 parts[2:], 
-                                                                 debug)
-                    return self.GetGlobalInstanceTagName(project, 
-                                                         config, 
-                                                         parts[1:],
-                                                         debug)
+        
+        instance_tagname_xslt_tree = etree.XSLT(
+            instance_tagname_xslt, 
+            extensions = {
+                ("instance_tagname_ns", "instance_definition"): InstanceDefinition(self, debug),
+                ("instance_tagname_ns", "config_tagname"): ConfigTagName(self),
+                ("instance_tagname_ns", "resource_tagname"): ResourceTagName(self),
+                ("instance_tagname_ns", "pou_tagname"): PouTagName(self),
+                ("instance_tagname_ns", "action_tagname"): ActionTagName(self),
+                ("instance_tagname_ns", "transition_tagname"): TransitionTagName(self)})
+        
+        result = instance_tagname_xslt_tree(project, 
+                instance_path=etree.XSLT.strparam(instance_path)).getroot()
+        if result is not None:
+            return result.text
+        
         return None
     
     def GetInstanceInfos(self, instance_path, debug = False):
@@ -1675,7 +1651,7 @@
             return False
         elif basetype_content_type == "derived":
             return self.IsLocatableType(basetype_content.getname())
-        elif basetype_content_name == "array":
+        elif basetype_content_type == "array":
             array_base_type = basetype_content.baseType.getcontent()
             if array_base_type.getLocalTag() == "derived":
                 return self.IsLocatableType(array_base_type.getname(), debug)
@@ -3076,10 +3052,10 @@
             return tasks_data, instances_data
 
     def OpenXMLFile(self, filepath):
-        try:
-            self.Project = LoadProject(filepath)
-        except Exception, e:
-            return _("Project file syntax error:\n\n") + str(e)
+        #try:
+        self.Project = LoadProject(filepath)
+        #except Exception, e:
+        #    return _("Project file syntax error:\n\n") + str(e)
         self.SetFilePath(filepath)
         self.CreateProjectBuffer(True)
         self.ProgramChunks = []
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/instance_tagname.xslt	Mon Sep 23 00:32:39 2013 +0200
@@ -0,0 +1,210 @@
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:ppx="http://www.plcopen.org/xml/tc6_0201"
+    xmlns:xhtml="http://www.w3.org/1999/xhtml"
+    xmlns:ns="instance_tagname_ns"
+    extension-element-prefixes="ns"
+    exclude-result-prefixes="ns">
+  <xsl:param name="instance_path"/>
+  <xsl:template name="element_name">
+    <xsl:param name="path"/>
+    <xsl:choose>
+      <xsl:when test="contains($path,'.')">
+        <xsl:value-of select="substring-before($path,'.')"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$path"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template name="next_path">
+    <xsl:param name="path"/>
+    <xsl:choose>
+      <xsl:when test="contains($path,'.')">
+        <xsl:value-of select="substring-after($path,'.')"/>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="ppx:project">
+    <xsl:variable name="config_name">
+      <xsl:call-template name="element_name">
+        <xsl:with-param name="path" select="$instance_path"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:apply-templates select="ppx:instances/ppx:configurations/ppx:configuration[@name=$config_name]">
+      <xsl:with-param name="element_path">
+        <xsl:call-template name="next_path">
+          <xsl:with-param name="path" select="$instance_path"/>
+        </xsl:call-template>
+      </xsl:with-param>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template match="ppx:configuration">
+    <xsl:param name="element_path"/>
+    <xsl:choose>
+      <xsl:when test="$element_path!=''">
+        <xsl:variable name="child_name">
+	      <xsl:call-template name="element_name">
+	        <xsl:with-param name="path" select="$element_path"/>
+	      </xsl:call-template>
+	    </xsl:variable>
+        <xsl:apply-templates select="ppx:resource[@name=$child_name] | ppx:globalVars/ppx:variable[@name=$child_name]/ppx:type/*[self::ppx:derived or self::ppx:struct or self::ppx:array]">
+          <xsl:with-param name="element_path">
+            <xsl:call-template name="next_path">
+		      <xsl:with-param name="path" select="$element_path"/>
+		    </xsl:call-template>
+		  </xsl:with-param>
+        </xsl:apply-templates>
+      </xsl:when>
+      <xsl:otherwise>
+        <ns:config_tagname>
+          <xsl:attribute name="name">
+            <xsl:value-of select="@name"/>
+          </xsl:attribute>
+        </ns:config_tagname>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="ppx:resource">
+    <xsl:param name="element_path"/>
+    <xsl:choose>
+      <xsl:when test="$element_path!=''">
+	    <xsl:variable name="child_name">
+	      <xsl:call-template name="element_name">
+	        <xsl:with-param name="path" select="$element_path"/>
+	      </xsl:call-template>
+	    </xsl:variable>
+        <xsl:apply-templates select="ppx:pouInstance[@name=$child_name] | ppx:task|ppx:pouInstance[@name=$child_name] | ppx:globalVars/ppx:variable[@name=$child_name]/ppx:type/*[self::ppx:derived or self::ppx:struct or self::ppx:array]">
+          <xsl:with-param name="element_path">
+            <xsl:call-template name="next_path">
+              <xsl:with-param name="path" select="$element_path"/>
+            </xsl:call-template>
+          </xsl:with-param>
+        </xsl:apply-templates>
+      </xsl:when>
+      <xsl:otherwise>
+        <ns:resource_tagname>
+          <xsl:attribute name="name">
+            <xsl:value-of select="@name"/>
+          </xsl:attribute>
+          <xsl:attribute name="config_name">
+            <xsl:value-of select="ancestor::ppx:configuration/@name"/>
+          </xsl:attribute>
+        </ns:resource_tagname>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="ppx:pouInstance">
+    <xsl:param name="element_path"/>
+    <ns:instance_definition>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@typeName"/>
+      </xsl:attribute>
+      <xsl:attribute name="path">
+        <xsl:value-of select="$element_path"/>
+      </xsl:attribute>
+    </ns:instance_definition>
+  </xsl:template>
+  <xsl:template match="ppx:pou">
+    <xsl:param name="element_path"/>
+    <xsl:variable name="child_name">
+      <xsl:call-template name="element_name">
+        <xsl:with-param name="path" select="$element_path"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="next_child_path">
+      <xsl:call-template name="next_path">
+        <xsl:with-param name="path" select="$element_path"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:apply-templates select="ppx:interface/*/ppx:variable[@name=$child_name]/ppx:type/*[self::ppx:derived or self::ppx:struct or self::ppx:array]">
+      <xsl:with-param name="next_child_path" select="next_child_path"/>
+    </xsl:apply-templates>
+    <xsl:apply-templates select="ppx:actions/ppx:action[@name=$child_name]">
+      <xsl:with-param name="next_child_path" select="next_child_path"/>
+    </xsl:apply-templates>
+    <xsl:apply-templates select="ppx:transitions/ppx:transition[@name=$child_name]">
+      <xsl:with-param name="next_child_path" select="next_child_path"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template match="ppx:action">
+    <ns:action_tagname>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:attribute name="pou_name">
+        <xsl:value-of select="ancestor::ppx:pou/@name"/>
+      </xsl:attribute>
+    </ns:action_tagname>
+  </xsl:template>
+  <xsl:template match="ppx:transition">
+    <ns:transition_tagname>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:attribute name="pou_name">
+        <xsl:value-of select="ancestor::ppx:pou/@name"/>
+      </xsl:attribute>
+    </ns:transition_tagname>
+  </xsl:template>
+  <xsl:template name="ppx:dataType">
+    <xsl:param name="element_path"/>
+    <xsl:apply-templates select="ppx:baseType/*[self::ppx:derived or self::ppx:struct or self::ppx:array]">
+      <xsl:with-param name="element_path" select="element_path"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template match="ppx:derived">
+    <xsl:param name="element_path"/>
+    <ns:instance_definition>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:attribute name="path">
+        <xsl:value-of select="$element_path"/>
+      </xsl:attribute>
+    </ns:instance_definition>
+  </xsl:template>
+  <xsl:template match="array">
+    <xsl:param name="element_path"/>
+    <xsl:apply-templates select="ppx:baseType/*[self::ppx:derived or self::ppx:struct or self::ppx:array]">
+      <xsl:with-param name="element_path" select="element_path"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template match="struct">
+    <xsl:param name="element_path"/>
+    <xsl:variable name="child_name">
+      <xsl:call-template name="element_name">
+        <xsl:with-param name="path" select="$element_path"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="next_child_path">
+      <xsl:call-template name="next_path">
+        <xsl:with-param name="path" select="$element_path"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:apply-templates select="ppx:variable[@name=$child_name]/ppx:type/*[self::ppx:derived or self::ppx:struct or self::ppx:array]">
+      <xsl:with-param name="element_path" select="element_path"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template match="pou_instance">
+    <xsl:choose>
+      <xsl:when test="@pou_path!=''">
+        <xsl:apply-templates>
+          <xsl:with-param name="element_path" select="@pou_path"/>
+        </xsl:apply-templates>        
+      </xsl:when>
+      <xsl:otherwise>
+        <ns:pou_tagname>
+          <xsl:attribute name="name">
+            <xsl:value-of select="ppx:pou/@name"/>
+          </xsl:attribute>
+        </ns:pou_tagname>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="datatype_instance">
+    <xsl:apply-templates>
+      <xsl:with-param name="element_path" select="@datatype_path"/>
+    </xsl:apply-templates>
+  </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file