Fixed pou variables instance information loading stylesheet
authorLaurent Bessard
Wed, 09 Oct 2013 22:00:23 +0200
changeset 1348 aee0a7eb833a
parent 1347 533741e5075c
child 1349 be6c3a036844
Fixed pou variables instance information loading stylesheet
PLCControler.py
controls/PouInstanceVariablesPanel.py
plcopen/pou_variables.xslt
plcopen/pou_variables.ysl2
--- a/PLCControler.py	Wed Oct 09 10:57:20 2013 +0200
+++ b/PLCControler.py	Wed Oct 09 22:00:23 2013 +0200
@@ -189,85 +189,54 @@
 #            Helpers object for generating pou variable instance list
 #-------------------------------------------------------------------------------
 
-def class_extraction(el, prt):
-    if prt in ["pou", "variable"]:
-        pou_type = POU_TYPES.get(el.text)
-        if pou_type is not None:
-            return pou_type
-        return VAR_CLASS_INFOS[el.text][1]
-    return {
+def class_extraction(value):
+    class_type = {
         "configuration": ITEM_CONFIGURATION,
         "resource": ITEM_RESOURCE,
         "action": ITEM_ACTION,
         "transition": ITEM_TRANSITION,
-        "program": ITEM_PROGRAM}.get(prt)
-
-PARAM_VALUE_EXTRACTION = {
-    "name": lambda el, prt: el.text,
-    "class": class_extraction,
-    "type": lambda el, prt: None if el.text == "None" else el.text,
-    "edit": lambda el, prt: el.text == "True",
-    "debug": lambda el, prt: el.text == "True",
-    "variables": lambda el, prt: [
-        compute_instance_tree(chld)
-        for chld in el]}
-
-def compute_instance_tree(tree):
-    return {el.tag:
-        PARAM_VALUE_EXTRACTION[el.tag](el, tree.tag)
-        for el in tree}
-
-class IsEdited(etree.XSLTExtension):
-    
-    def __init__(self, controller, debug):
-        etree.XSLTExtension.__init__(self)
-        self.Controller = controller
-        self.Debug = debug
-    
-    def execute(self, context, self_node, input_node, output_parent):
-        typename = input_node.get("name")
-        project = self.Controller.GetProject(self.Debug)
-        output_parent.text = str(project.getpou(typename) is not None)
-        
-class IsDebugged(etree.XSLTExtension):
-    
-    def __init__(self, controller, debug):
-        etree.XSLTExtension.__init__(self)
-        self.Controller = controller
-        self.Debug = debug
-    
-    def execute(self, context, self_node, input_node, output_parent):
-        typename = input_node.get("name")
-        project = self.Controller.GetProject(self.Debug)
-        pou_infos = project.getpou(typename)
-        if pou_infos is not None:
-            self.apply_templates(context, pou_infos, output_parent)
-            return
-        
-        datatype_infos = self.Controller.GetDataType(typename, self.Debug)
-        if datatype_infos is not None:
-            self.apply_templates(context, datatype_infos, output_parent)
-            return
-        
-        output_parent.text = "False"
-        
-class PouVariableClass(etree.XSLTExtension):
-    
-    def __init__(self, controller, debug):
-        etree.XSLTExtension.__init__(self)
-        self.Controller = controller
-        self.Debug = debug
-    
-    def execute(self, context, self_node, input_node, output_parent):
-        pou_infos = self.Controller.GetPou(input_node.get("name"), self.Debug)
-        if pou_infos is not None:
-            self.apply_templates(context, pou_infos, output_parent)
-            return
-        
-        self.process_children(context, output_parent)
-        
-pou_variables_xslt = etree.parse(
-    os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt"))
+        "program": ITEM_PROGRAM}.get(value)
+    if class_type is not None:
+        return class_type
+    
+    pou_type = POU_TYPES.get(value)
+    if pou_type is not None:
+        return pou_type
+    
+    var_type = VAR_CLASS_INFOS.get(value)
+    if var_type is not None:
+        return var_type[1]
+    
+    return None
+
+class _VariablesTreeItemInfos(object):
+    __slots__ = ["name", "var_class", "type", "edit", "debug", "variables"]
+    def __init__(self, *args):
+        for attr, value in zip(self.__slots__, args):
+            setattr(self, attr, value if value is not None else "")
+    def copy(self):
+        return _VariableTreeItem(*[getattr(self, attr) for attr in self.__slots__])
+
+class VariablesTreeInfosFactory:
+    
+    def __init__(self):
+        self.Root = None
+    
+    def GetRoot(self):
+        return self.Root
+    
+    def SetRoot(self, context, *args):
+        self.Root = _VariablesTreeItemInfos(
+            *([''] + _translate_args(
+                [class_extraction, str] + [_BoolValue] * 2, 
+                args) + [[]]))
+
+    def AddVariable(self, context, *args):
+        if self.Root is not None:
+            self.Root.variables.append(_VariablesTreeItemInfos(
+                *(_translate_args(
+                    [str, class_extraction, str] + [_BoolValue] * 2, 
+                    args) + [[]])))
 
 #-------------------------------------------------------------------------------
 #            Helpers object for generating instances path list
@@ -799,20 +768,28 @@
         pou_type = None
         project = self.GetProject(debug)
         if project is not None:
+            factory = VariablesTreeInfosFactory()
+            
+            parser = etree.XMLParser()
+            parser.resolvers.add(LibraryResolver(self, debug))
+            
             pou_variable_xslt_tree = etree.XSLT(
-                pou_variables_xslt, extensions = {
-                    ("pou_vars_ns", "is_edited"): IsEdited(self, debug),
-                    ("pou_vars_ns", "is_debugged"): IsDebugged(self, debug),
-                    ("pou_vars_ns", "pou_class"): PouVariableClass(self, debug)})
+                etree.parse(
+                    os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt"),
+                    parser), 
+                extensions = {("pou_vars_ns", name): getattr(factory, name)
+                              for name in ["SetRoot", "AddVariable"]})
             
+            obj = None
             words = tagname.split("::")
             if words[0] == "P":
                 obj = self.GetPou(words[1], debug)
-            else:
+            elif words[0] != "D":
                 obj = self.GetEditedElement(tagname, debug)
             if obj is not None:
-                return compute_instance_tree(
-                        pou_variable_xslt_tree(obj).getroot())
+                pou_variable_xslt_tree(obj)
+                return factory.GetRoot()
+            
         return None
 
     def GetInstanceList(self, root, name, debug = False):
--- a/controls/PouInstanceVariablesPanel.py	Wed Oct 09 10:57:20 2013 +0200
+++ b/controls/PouInstanceVariablesPanel.py	Wed Oct 09 22:00:23 2013 +0200
@@ -244,27 +244,27 @@
             self.PouInfos = None
         if self.PouInfos is not None:
             root = self.VariablesList.AddRoot("")
-            for var_infos in self.PouInfos["variables"]:
-                if var_infos.get("type", None) is not None:
-                    text = "%(name)s (%(type)s)" % var_infos
+            for var_infos in self.PouInfos.variables:
+                if var_infos.type is not None:
+                    text = "%s (%s)" % (var_infos.name, var_infos.type)
                 else:
-                    text = var_infos["name"]
+                    text = var_infos.name
                 
                 right_images = []
-                if var_infos["class"] in ITEMS_VARIABLE:
-                    if (not USE_MPL and var_infos["debug"] and self.Debug and
-                        (self.Controller.IsOfType(var_infos["type"], "ANY_NUM", True) or
-                         self.Controller.IsOfType(var_infos["type"], "ANY_BIT", True))):
+                if var_infos.var_class in ITEMS_VARIABLE:
+                    if (not USE_MPL and var_infos.debug and self.Debug and
+                        (self.Controller.IsOfType(var_infos.type, "ANY_NUM", True) or
+                         self.Controller.IsOfType(var_infos.type, "ANY_BIT", True))):
                         right_images.append(self.InstanceGraphImage)
-                elif var_infos["edit"]:
+                elif var_infos.edit:
                     right_images.append(self.EditImage)
                 
-                if var_infos["debug"] and self.Debug:
+                if var_infos.debug and self.Debug:
                     right_images.append(self.DebugInstanceImage)
                 
                 item = self.VariablesList.AppendItem(root, text)
                 item.SetRightImages(right_images)
-                self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos["class"]))
+                self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos.var_class))
                 self.VariablesList.SetPyData(item, var_infos)
             
         self.RefreshInstanceChoice()
@@ -281,7 +281,7 @@
                 self.InstanceChoice.Append(instance)
             if len(instances) == 1:
                 self.PouInstance = instances[0]
-            if self.PouInfos["class"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]:
+            if self.PouInfos.var_class in [ITEM_CONFIGURATION, ITEM_RESOURCE]:
                 self.PouInstance = None
                 self.InstanceChoice.SetSelection(0)
             elif self.PouInstance in instances:
@@ -292,8 +292,8 @@
     
     def RefreshButtons(self):
         enabled = self.InstanceChoice.GetSelection() != -1
-        self.ParentButton.Enable(enabled and self.PouInfos["class"] != ITEM_CONFIGURATION)
-        self.DebugButton.Enable(enabled and self.PouInfos["debug"] and self.Debug)
+        self.ParentButton.Enable(enabled and self.PouInfos.var_class != ITEM_CONFIGURATION)
+        self.DebugButton.Enable(enabled and self.PouInfos.debug and self.Debug)
         
         root = self.VariablesList.GetRootItem()
         if root is not None and root.IsOk():
@@ -307,29 +307,29 @@
                 item, item_cookie = self.VariablesList.GetNextChild(root, item_cookie)
     
     def EditButtonCallback(self, infos):
-        var_class = infos["class"]
+        var_class = infos.var_class
         if var_class == ITEM_RESOURCE:
             tagname = self.Controller.ComputeConfigurationResourceName(
                 self.InstanceChoice.GetStringSelection(), 
-                infos["name"])
+                infos.name)
         elif var_class == ITEM_TRANSITION:
             tagname = self.Controller.ComputePouTransitionName(
                 self.PouTagName.split("::")[1],
-                infos["name"])
+                infos.name)
         elif var_class == ITEM_ACTION:
             tagname = self.Controller.ComputePouActionName(
                 self.PouTagName.split("::")[1],
-                infos["name"])
+                infos.name)
         else:
             var_class = ITEM_POU
-            tagname = self.Controller.ComputePouName(infos["type"])
+            tagname = self.Controller.ComputePouName(infos.type)
         self.ParentWindow.EditProjectElement(var_class, tagname)
     
     def DebugButtonCallback(self, infos):
         if self.InstanceChoice.GetSelection() != -1:
-            var_class = infos["class"]
+            var_class = infos.var_class
             var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), 
-                                  infos["name"])
+                                  infos.name)
             if var_class in ITEMS_VARIABLE:
                 self.ParentWindow.AddDebugVariable(var_path, force=True)
             elif var_class == ITEM_TRANSITION:
@@ -338,35 +338,35 @@
                     var_path,
                     self.Controller.ComputePouTransitionName(
                         self.PouTagName.split("::")[1],
-                        infos["name"]))
+                        infos.name))
             elif var_class == ITEM_ACTION:
                 self.ParentWindow.OpenDebugViewer(
                     var_class,
                     var_path,
                     self.Controller.ComputePouActionName(
                         self.PouTagName.split("::")[1],
-                        infos["name"]))
+                        infos.name))
             else:
                 self.ParentWindow.OpenDebugViewer(
                     var_class,
                     var_path,
-                    self.Controller.ComputePouName(infos["type"]))
+                    self.Controller.ComputePouName(infos.type))
     
     def DebugButtonDClickCallback(self, infos):
         if self.InstanceChoice.GetSelection() != -1:
-            if infos["class"] in ITEMS_VARIABLE:
+            if infos.var_class in ITEMS_VARIABLE:
                 self.ParentWindow.AddDebugVariable(
                     "%s.%s" % (self.InstanceChoice.GetStringSelection(), 
-                               infos["name"]), 
+                               infos.name), 
                     force=True,
                     graph=True)
     
     def GraphButtonCallback(self, infos):
         if self.InstanceChoice.GetSelection() != -1:
-            if infos["class"] in ITEMS_VARIABLE:
+            if infos.var_class in ITEMS_VARIABLE:
                 var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), 
-                                      infos["name"])
-                self.ParentWindow.OpenDebugViewer(infos["class"], var_path, infos["type"])
+                                      infos.name)
+                self.ParentWindow.OpenDebugViewer(infos.var_class, var_path, infos.type)
     
     def ShowInstanceChoicePopup(self):
         self.InstanceChoice.SetFocusFromKbd()
@@ -395,7 +395,7 @@
     def OnDebugButtonClick(self, event):
         if self.InstanceChoice.GetSelection() != -1:
             self.ParentWindow.OpenDebugViewer(
-                self.PouInfos["class"],
+                self.PouInfos.var_class,
                 self.InstanceChoice.GetStringSelection(),
                 self.PouTagName)
         event.Skip()
@@ -413,20 +413,20 @@
                     if callback is not None:
                         callback(item_infos)
                 
-                elif item_infos["class"] not in ITEMS_VARIABLE:
+                elif item_infos.var_class not in ITEMS_VARIABLE:
                     instance_path = self.InstanceChoice.GetStringSelection()
-                    if item_infos["class"] == ITEM_RESOURCE:
+                    if item_infos.var_class == ITEM_RESOURCE:
                         if instance_path != "":
                             tagname = self.Controller.ComputeConfigurationResourceName(
                                            instance_path, 
-                                           item_infos["name"])
+                                           item_infos.name)
                         else:
                             tagname = None
                     else:
-                        tagname = self.Controller.ComputePouName(item_infos["type"])
+                        tagname = self.Controller.ComputePouName(item_infos.type)
                     if tagname is not None:
                         if instance_path != "":
-                            item_path = "%s.%s" % (instance_path, item_infos["name"])
+                            item_path = "%s.%s" % (instance_path, item_infos.name)
                         else:
                             item_path = None
                         self.SetPouType(tagname, item_path)
@@ -450,10 +450,10 @@
                         if callback is not None:
                             callback(item_infos)
                 
-                elif flags & CT.TREE_HITTEST_ONITEMLABEL and item_infos["class"] in ITEMS_VARIABLE:
+                elif flags & CT.TREE_HITTEST_ONITEMLABEL and item_infos.var_class in ITEMS_VARIABLE:
                     self.ParentWindow.EnsureTabVisible(
                         self.ParentWindow.DebugVariablePanel)
-                    item_path = "%s.%s" % (instance_path, item_infos["name"])
+                    item_path = "%s.%s" % (instance_path, item_infos.name)
                     data = wx.TextDataObject(str((item_path, "debug")))
                     dragSource = wx.DropSource(self.VariablesList)
                     dragSource.SetData(data)
--- a/plcopen/pou_variables.xslt	Wed Oct 09 10:57:20 2013 +0200
+++ b/plcopen/pou_variables.xslt	Wed Oct 09 22:00:23 2013 +0200
@@ -1,174 +1,299 @@
-<xsl:stylesheet version="1.0"
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-    xmlns:ppx="http://www.plcopen.org/xml/tc6_0201"
-    xmlns:ns="pou_vars_ns"
-    extension-element-prefixes="ns"
-    exclude-result-prefixes="ns">
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:func="http://exslt.org/functions" xmlns:dyn="http://exslt.org/dynamic" xmlns:str="http://exslt.org/strings" xmlns:math="http://exslt.org/math" xmlns:exsl="http://exslt.org/common" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:yml="http://fdik.org/yml" xmlns:set="http://exslt.org/sets" xmlns:ppx="http://www.plcopen.org/xml/tc6_0201" xmlns:ns="pou_vars_ns" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="ns" version="1.0" exclude-result-prefixes="ns">
+  <xsl:output method="xml"/>
+  <xsl:variable name="space" select="'                                                                                                                                                                                                        '"/>
+  <xsl:param name="autoindent" select="4"/>
+  <xsl:template match="text()">
+    <xsl:param name="_indent" select="0"/>
+  </xsl:template>
+  <xsl:template mode="var_class" match="text()">
+    <xsl:param name="_indent" select="0"/>
+  </xsl:template>
+  <xsl:template mode="var_type" match="text()">
+    <xsl:param name="_indent" select="0"/>
+  </xsl:template>
+  <xsl:template mode="var_edit" match="text()">
+    <xsl:param name="_indent" select="0"/>
+  </xsl:template>
+  <xsl:template mode="var_debug" match="text()">
+    <xsl:param name="_indent" select="0"/>
+  </xsl:template>
+  <xsl:variable name="project">
+    <xsl:copy-of select="document('project')/project/*"/>
+  </xsl:variable>
+  <xsl:variable name="stdlib">
+    <xsl:copy-of select="document('stdlib')/stdlib/*"/>
+  </xsl:variable>
+  <xsl:variable name="extensions">
+    <xsl:copy-of select="document('extensions')/extensions/*"/>
+  </xsl:variable>
+  <xsl:template name="add_root">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:param name="class"/>
+    <xsl:param name="type"/>
+    <xsl:param name="edit">
+      <xsl:text>true</xsl:text>
+    </xsl:param>
+    <xsl:param name="debug">
+      <xsl:text>true</xsl:text>
+    </xsl:param>
+    <xsl:value-of select="ns:SetRoot($class, $type, $edit, $debug)"/>
+  </xsl:template>
   <xsl:template match="ppx:pou">
-    <pou>
-      <class><xsl:value-of select="@pouType"/></class>
-      <type><xsl:value-of select="@name"/></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>True</xsl:text></debug>
-      <variables>
-        <xsl:apply-templates select="ppx:interface"/>
-        <xsl:apply-templates select="ppx:actions/ppx:action | ppx:transitions/ppx:transition" mode="variable_list"/>
-      </variables>
-    </pou>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_root">
+      <xsl:with-param name="class">
+        <xsl:value-of select="@pouType"/>
+      </xsl:with-param>
+      <xsl:with-param name="type">
+        <xsl:value-of select="@name"/>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:apply-templates select="ppx:interface">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
+    <xsl:apply-templates mode="variable_list" select="ppx:actions/ppx:action | ppx:transitions/ppx:transition">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
   </xsl:template>
   <xsl:template match="ppx:action">
-    <action>
-      <class/>
-      <type><xsl:text>None</xsl:text></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>True</xsl:text></debug>
-      <variables>
-        <xsl:apply-templates select="ancestor::ppx:pou/child::ppx:interface"/>
-      </variables>
-    </action>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_root">
+      <xsl:with-param name="class">
+        <xsl:text>action</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:apply-templates select="ancestor::ppx:pou/child::ppx:interface">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
   </xsl:template>
   <xsl:template match="ppx:transition">
-    <transition>
-      <class/>
-      <type><xsl:text>None</xsl:text></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>True</xsl:text></debug>
-      <variables>
-        <xsl:apply-templates select="ancestor::ppx:pou/child::ppx:interface"/>
-      </variables>
-    </transition>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_root">
+      <xsl:with-param name="class">
+        <xsl:text>transition</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:apply-templates select="ancestor::ppx:pou/child::ppx:interface">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
   </xsl:template>
   <xsl:template match="ppx:configuration">
-    <configuration>
-      <class/>
-      <type><xsl:text>None</xsl:text></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>False</xsl:text></debug>
-      <variables>
-        <xsl:apply-templates select="ppx:resource" mode="variable_list"/>
-        <xsl:apply-templates select="ppx:globalVars"/>
-      </variables>
-    </configuration>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_root">
+      <xsl:with-param name="class">
+        <xsl:text>configuration</xsl:text>
+      </xsl:with-param>
+      <xsl:with-param name="debug">
+        <xsl:text>false</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:apply-templates mode="variable_list" select="ppx:resource">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
+    <xsl:apply-templates select="ppx:globalVars">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
   </xsl:template>
   <xsl:template match="ppx:resource">
-    <resource>
-      <class/>
-      <type><xsl:text>None</xsl:text></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>False</xsl:text></debug>
-      <variables>
-        <xsl:apply-templates select="ppx:pouInstance | ppx:task/ppx:pouInstance" mode="variable_list"/>
-        <xsl:apply-templates select="ppx:globalVars"/>
-      </variables>
-    </resource>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_root">
+      <xsl:with-param name="class">
+        <xsl:text>resource</xsl:text>
+      </xsl:with-param>
+      <xsl:with-param name="debug">
+        <xsl:text>false</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:apply-templates mode="variable_list" select="ppx:pouInstance | ppx:task/ppx:pouInstance">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
+    <xsl:apply-templates select="ppx:globalVars">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template name="variables_infos">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:param name="var_class"/>
+    <xsl:for-each select="ppx:variable">
+      <xsl:variable name="class">
+        <xsl:apply-templates mode="var_class" select="ppx:type">
+          <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+          <xsl:with-param name="default_class">
+            <xsl:value-of select="$var_class"/>
+          </xsl:with-param>
+        </xsl:apply-templates>
+      </xsl:variable>
+      <xsl:variable name="type">
+        <xsl:apply-templates mode="var_type" select="ppx:type">
+          <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+        </xsl:apply-templates>
+      </xsl:variable>
+      <xsl:variable name="edit">
+        <xsl:apply-templates mode="var_edit" select="ppx:type">
+          <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+        </xsl:apply-templates>
+      </xsl:variable>
+      <xsl:variable name="debug">
+        <xsl:apply-templates mode="var_debug" select="ppx:type">
+          <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+        </xsl:apply-templates>
+      </xsl:variable>
+      <xsl:value-of select="ns:AddVariable(@name, $class, $type, $edit, $debug)"/>
+    </xsl:for-each>
   </xsl:template>
   <xsl:template match="ppx:localVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'Local'"/>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>Local</xsl:text>
+      </xsl:with-param>
     </xsl:call-template>
   </xsl:template>
   <xsl:template match="ppx:globalVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'Global'"/>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>Global</xsl:text>
+      </xsl:with-param>
     </xsl:call-template>
   </xsl:template>
   <xsl:template match="ppx:externalVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'External'"/>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>External</xsl:text>
+      </xsl:with-param>
     </xsl:call-template>
   </xsl:template>
   <xsl:template match="ppx:tempVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'Temp'"/>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>Temp</xsl:text>
+      </xsl:with-param>
     </xsl:call-template>
   </xsl:template>
   <xsl:template match="ppx:inputVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'Input'"/>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>Input</xsl:text>
+      </xsl:with-param>
     </xsl:call-template>
   </xsl:template>
   <xsl:template match="ppx:outputVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'Output'"/>
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>Output</xsl:text>
+      </xsl:with-param>
     </xsl:call-template>
   </xsl:template>
   <xsl:template match="ppx:inOutVars">
-    <xsl:call-template name="variables_infos">
-      <xsl:with-param name="var_class" select="'InOut'"/>
-    </xsl:call-template>
-  </xsl:template>
-  <xsl:template name="variables_infos">
-    <xsl:param name="var_class"/>
-	<xsl:for-each select="ppx:variable">
-      <variable>
-	    <name><xsl:value-of select="@name"/></name>
-	    <class>
-	      <xsl:apply-templates mode="var_class">
-	        <xsl:with-param name="default_class">
-	          <xsl:value-of select="$var_class"/>
-	        </xsl:with-param>
-	      </xsl:apply-templates>
-	    </class>
-	    <type><xsl:apply-templates mode="var_type"/></type>
-	    <edit><xsl:apply-templates mode="var_edit"/></edit>
-	    <debug><xsl:apply-templates mode="var_debug"/></debug>
-      </variable>
-    </xsl:for-each>
-  </xsl:template>
-  <xsl:template match="ppx:transition" mode="variable_list">
-    <transition>
-      <name><xsl:value-of select="@name"/></name>
-      <class/>
-      <type><xsl:text>None</xsl:text></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>True</xsl:text></debug>
-    </transition>
-  </xsl:template>
-  <xsl:template match="ppx:action" mode="variable_list">
-    <action>
-	  <name><xsl:value-of select="@name"/></name>
-	  <class/>
-      <type><xsl:text>None</xsl:text></type>
-	  <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>True</xsl:text></debug>
-    </action>
-  </xsl:template>
-  <xsl:template match="ppx:resource" mode="variable_list">
-    <resource>
-      <name><xsl:value-of select="@name"/></name>
-      <class/>
-      <type><xsl:text>None</xsl:text></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>False</xsl:text></debug>
-    </resource>
-  </xsl:template>
-  <xsl:template match="ppx:pouInstance" mode="variable_list">
-    <program>
-      <name><xsl:value-of select="@name"/></name>
-      <class/>
-      <type><xsl:value-of select="@typeName"/></type>
-      <edit><xsl:text>True</xsl:text></edit>
-      <debug><xsl:text>True</xsl:text></debug>
-    </program>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:derived" mode="var_class">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="variables_infos">
+      <xsl:with-param name="var_class">
+        <xsl:text>InOut</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="add_variable">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:param name="name"/>
+    <xsl:param name="class"/>
+    <xsl:param name="type"/>
+    <xsl:param name="edit">
+      <xsl:text>true</xsl:text>
+    </xsl:param>
+    <xsl:param name="debug">
+      <xsl:text>true</xsl:text>
+    </xsl:param>
+    <xsl:value-of select="ns:AddVariable($name, $class, $type, $edit, $debug)"/>
+  </xsl:template>
+  <xsl:template mode="variable_list" match="ppx:action">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_variable">
+      <xsl:with-param name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:with-param>
+      <xsl:with-param name="class">
+        <xsl:text>action</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template mode="variable_list" match="ppx:transition">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_variable">
+      <xsl:with-param name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:with-param>
+      <xsl:with-param name="class">
+        <xsl:text>transition</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template mode="variable_list" match="ppx:resource">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_variable">
+      <xsl:with-param name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:with-param>
+      <xsl:with-param name="class">
+        <xsl:text>resource</xsl:text>
+      </xsl:with-param>
+      <xsl:with-param name="debug">
+        <xsl:text>false</xsl:text>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template mode="variable_list" match="ppx:pouInstance">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:call-template name="add_variable">
+      <xsl:with-param name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:with-param>
+      <xsl:with-param name="class">
+        <xsl:text>program</xsl:text>
+      </xsl:with-param>
+      <xsl:with-param name="type">
+        <xsl:value-of select="@typeName"/>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template mode="var_class" match="*[self::ppx:type or self::ppx:baseType]/ppx:derived">
+    <xsl:param name="_indent" select="0"/>
     <xsl:param name="default_class"/>
-    <ns:pou_class>
-      <xsl:value-of select="$default_class"/>
-    </ns:pou_class>
-  </xsl:template>
-  <xsl:template match="ppx:pou" mode="var_class">
-    <xsl:param name="default_class"/>
+    <xsl:variable name="type_name" select="@name"/>
+    <xsl:variable name="pou_infos">
+      <xsl:copy-of select="exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                    exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                    exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]"/>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$pou_infos != ''">
+        <xsl:apply-templates mode="var_class" select="exsl:node-set($pou_infos)">
+          <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+        </xsl:apply-templates>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$default_class"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template mode="var_class" match="ppx:pou">
+    <xsl:param name="_indent" select="0"/>
     <xsl:value-of select="@pouType"/>
   </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/*" mode="var_class">
+  <xsl:template mode="var_class" match="*[self::ppx:type or self::ppx:baseType]/*">
+    <xsl:param name="_indent" select="0"/>
     <xsl:param name="default_class"/>
     <xsl:value-of select="$default_class"/>
   </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:derived" mode="var_type">
+  <xsl:template mode="var_type" match="*[self::ppx:type or self::ppx:baseType]/ppx:derived">
+    <xsl:param name="_indent" select="0"/>
     <xsl:value-of select="@name"/>
   </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:array" mode="var_type">
+  <xsl:template mode="var_type" match="*[self::ppx:type or self::ppx:baseType]/ppx:array">
+    <xsl:param name="_indent" select="0"/>
     <xsl:text>ARRAY [</xsl:text>
     <xsl:for-each select="ppx:dimension">
       <xsl:value-of select="@lower"/>
@@ -176,44 +301,78 @@
       <xsl:value-of select="@upper"/>
     </xsl:for-each>
     <xsl:text>] OF </xsl:text>
-    <xsl:apply-templates select="ppx:baseType" mode="var_type"/>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:string" mode="var_type">
+    <xsl:apply-templates mode="var_type" select="ppx:baseType">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template mode="var_type" match="*[self::ppx:type or self::ppx:baseType]/ppx:string">
+    <xsl:param name="_indent" select="0"/>
     <xsl:text>STRING</xsl:text>
   </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:wstring" mode="var_type">
+  <xsl:template mode="var_type" match="*[self::ppx:type or self::ppx:baseType]/ppx:wstring">
+    <xsl:param name="_indent" select="0"/>
     <xsl:text>WSTRING</xsl:text>
   </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/*" mode="var_type">
+  <xsl:template mode="var_type" match="*[self::ppx:type or self::ppx:baseType]/*">
+    <xsl:param name="_indent" select="0"/>
     <xsl:value-of select="local-name()"/>
   </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:derived" mode="var_edit">
-    <ns:is_edited/>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:array" mode="var_edit">
-    <xsl:apply-templates select="ppx:baseType" mode="var_edit"/>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/*" mode="var_edit">
-    <xsl:text>False</xsl:text>
-  </xsl:template>
-    <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:derived" mode="var_debug">
-    <ns:is_debugged/>
-  </xsl:template>
-  <xsl:template match="ppx:pou" mode="var_debug">
-    <xsl:text>True</xsl:text>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:array" mode="var_debug">
-    <xsl:text>False</xsl:text>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/ppx:struct" mode="var_debug">
-    <xsl:text>False</xsl:text>
-  </xsl:template>
-  <xsl:template match="*[self::ppx:type or self::ppx:baseType]/*" mode="var_debug">
-    <xsl:text>True</xsl:text>
-  </xsl:template>
-  <xsl:template match="text()"/>
-  <xsl:template match="text()" mode="var_class"/>
-  <xsl:template match="text()" mode="var_type"/>
-  <xsl:template match="text()" mode="var_edit"/>
-  <xsl:template match="text()" mode="var_debug"/>
-</xsl:stylesheet>
\ No newline at end of file
+  <xsl:template mode="var_edit" match="*[self::ppx:type or self::ppx:baseType]/ppx:derived">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:variable name="type_name" select="@name"/>
+    <xsl:variable name="pou_infos">
+      <xsl:copy-of select="exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]"/>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$pou_infos != ''">
+        <xsl:text>true</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:text>false</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template mode="var_edit" match="*[self::ppx:type or self::ppx:baseType]/ppx:array">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:apply-templates mode="var_edit" select="ppx:baseType">
+      <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  <xsl:template mode="var_edit" match="*[self::ppx:type or self::ppx:baseType]/*">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:text>false</xsl:text>
+  </xsl:template>
+  <xsl:template mode="var_debug" match="*[self::ppx:type or self::ppx:baseType]/ppx:derived">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:variable name="type_name" select="@name"/>
+    <xsl:variable name="datatype_infos">
+      <xsl:copy-of select="exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |&#10;                    exsl:node-set($project)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |&#10;                    exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |&#10;                    exsl:node-set($extensions)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name]"/>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$datatype_infos != ''">
+        <xsl:apply-templates mode="var_debug" select="exsl:node-set($datatype_infos)">
+          <xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/>
+        </xsl:apply-templates>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:text>false</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template mode="var_debug" match="ppx:pou">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:text>true</xsl:text>
+  </xsl:template>
+  <xsl:template mode="var_debug" match="*[self::ppx:type or self::ppx:baseType]/ppx:array">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:text>false</xsl:text>
+  </xsl:template>
+  <xsl:template mode="var_debug" match="*[self::ppx:type or self::ppx:baseType]/ppx:struct">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:text>false</xsl:text>
+  </xsl:template>
+  <xsl:template mode="var_debug" match="*[self::ppx:type or self::ppx:baseType]/*">
+    <xsl:param name="_indent" select="0"/>
+    <xsl:text>true</xsl:text>
+  </xsl:template>
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/pou_variables.ysl2	Wed Oct 09 22:00:23 2013 +0200
@@ -0,0 +1,279 @@
+include yslt.yml2
+estylesheet xmlns:ppx="http://www.plcopen.org/xml/tc6_0201"
+            xmlns:xhtml="http://www.w3.org/1999/xhtml"
+            xmlns:ns="pou_vars_ns" 
+            extension-element-prefixes="ns" 
+            exclude-result-prefixes="ns" {
+    
+    template "text()";
+    template "text()", mode="var_class";
+    template "text()", mode="var_type";
+    template "text()", mode="var_edit";
+    template "text()", mode="var_debug";
+    
+    variable "project" {
+        copy "document('project')/project/*";
+    }
+    
+    variable "stdlib" {
+        copy "document('stdlib')/stdlib/*";
+    }
+    variable "extensions" {
+        copy "document('extensions')/extensions/*";
+    }
+    
+    function "add_root" {
+        param "class";
+        param "type";
+        param "edit" > true
+        param "debug" > true
+        value "ns:SetRoot($class, $type, $edit, $debug)";
+    }
+    
+    template "ppx:pou" {
+        call "add_root" {
+            with "class" > «@pouType»
+            with "type" > «@name»
+        }
+        apply "ppx:interface";
+        apply "ppx:actions/ppx:action | ppx:transitions/ppx:transition", mode="variable_list";
+    }
+    
+    template "ppx:action" {
+        call "add_root" {
+            with "class" > action
+        }
+        apply "ancestor::ppx:pou/child::ppx:interface";
+    }
+    
+    template "ppx:transition" {
+        call "add_root" {
+            with "class" > transition
+        }
+        apply "ancestor::ppx:pou/child::ppx:interface";
+    }
+    
+    template "ppx:configuration" {
+        call "add_root" {
+            with "class" > configuration
+            with "debug" > false
+        }
+        apply "ppx:resource", mode="variable_list";
+        apply "ppx:globalVars";
+    }
+    
+    template "ppx:resource" {
+        call "add_root" {
+            with "class" > resource
+            with "debug" > false
+        }
+        apply "ppx:pouInstance | ppx:task/ppx:pouInstance",  mode="variable_list";
+        apply "ppx:globalVars";
+    }
+    
+    function "variables_infos" {
+        param "var_class";
+        foreach "ppx:variable" {
+            variable "class" {
+                apply "ppx:type", mode="var_class" {
+                    with "default_class" > «$var_class»
+                }
+            }
+            variable "type" {
+                apply"ppx:type", mode="var_type";
+            }
+            variable "edit" {
+                apply "ppx:type", mode="var_edit";
+            }
+            variable "debug" {
+                apply "ppx:type", mode="var_debug";
+            }
+            value "ns:AddVariable(@name, $class, $type, $edit, $debug)";
+        }
+    }
+    
+    template "ppx:localVars" {
+        call "variables_infos" {
+            with "var_class" > Local
+        }
+    }
+    
+    template "ppx:globalVars" {
+        call "variables_infos" {
+            with "var_class" > Global
+        }
+    }
+    
+    template "ppx:externalVars" {
+        call "variables_infos" {
+            with "var_class" > External
+        }
+    }
+    
+    template "ppx:tempVars" {
+        call "variables_infos" {
+            with "var_class" > Temp
+        }
+    }
+    
+    template "ppx:inputVars" {
+        call "variables_infos" {
+            with "var_class" > Input
+        }
+    }
+    
+    template "ppx:outputVars" {
+        call "variables_infos" {
+            with "var_class" > Output
+        }
+    }
+    
+    template "ppx:inOutVars" {
+        call "variables_infos" {
+            with "var_class" > InOut
+        }
+    }
+    
+    function "add_variable" {
+        param "name";
+        param "class";
+        param "type";
+        param "edit" > true
+        param "debug" > true
+        value "ns:AddVariable($name, $class, $type, $edit, $debug)";
+    }
+    
+    template "ppx:action", mode="variable_list" {
+        call "add_variable" {
+            with "name" > «@name»
+            with "class" > action
+        }
+    }
+    
+    template "ppx:transition", mode="variable_list" {
+        call "add_variable" {
+            with "name" > «@name»
+            with "class" > transition
+        }
+    }
+    
+    template "ppx:resource", mode="variable_list" {
+        call "add_variable" {
+            with "name" > «@name»
+            with "class" > resource
+            with "debug" > false
+        } 
+    }
+    
+    template "ppx:pouInstance", mode="variable_list" {
+        call "add_variable" {
+            with "name" > «@name»
+            with "class" > program
+            with "type" > «@typeName»
+        }
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_class" {
+        param "default_class";
+        variable "type_name", "@name";
+        variable "pou_infos" {
+            copy """exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
+                    exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
+                    exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]""";
+        }
+        choose {
+            when "$pou_infos != ''" {
+                apply "exsl:node-set($pou_infos)", mode="var_class";
+            }
+            otherwise {
+                value "$default_class"
+            }
+        }
+    }
+    
+    template "ppx:pou", mode="var_class" {
+        value "@pouType";
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/*" mode="var_class" {
+        param "default_class";
+        value "$default_class";
+    }
+  
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_type" {
+        > «@name»
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:array", mode="var_type" {
+        > ARRAY [
+        foreach "ppx:dimension" {
+            > «@lower»..«@upper»
+        }
+        > ] OF 
+        apply "ppx:baseType", mode="var_type";
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:string", mode="var_type" {
+        > STRING
+    }
+  
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:wstring", mode="var_type" {
+        > WSTRING
+    }
+  
+    template "*[self::ppx:type or self::ppx:baseType]/*", mode="var_type" {
+        > «local-name()»
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_edit" {
+        variable "type_name", "@name";
+        variable "pou_infos" {
+            copy "exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]";
+        }
+        choose {
+            when "$pou_infos != ''" > true
+            otherwise > false
+        }
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:array", mode="var_edit" {
+        apply "ppx:baseType", mode="var_edit";
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/*", mode="var_edit" {
+        > false
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_debug" {
+        variable "type_name", "@name";
+        variable "datatype_infos" {
+            copy """exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] |
+                    exsl:node-set($project)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |
+                    exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] |
+                    exsl:node-set($extensions)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name]""";
+        }
+        choose {
+            when "$datatype_infos != ''" {
+                apply "exsl:node-set($datatype_infos)", mode="var_debug";
+            }
+            otherwise > false
+        }
+    }
+    
+    template "ppx:pou", mode="var_debug" {
+        > true
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:array", mode="var_debug" {
+        > false
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/ppx:struct", mode="var_debug" {
+        > false
+    }
+    
+    template "*[self::ppx:type or self::ppx:baseType]/*", mode="var_debug" {
+        > true
+    }
+    
+}