Fixed xslt stylesheet for extracting entries defined in module, rewiting xslt stylesheet to yslt
authorLaurent Bessard
Wed, 02 Oct 2013 10:46:18 +0200
changeset 2162 43ab74687f45
parent 2161 4bea1d98db46
child 2163 6ea6d83e7280
Fixed xslt stylesheet for extracting entries defined in module, rewiting xslt stylesheet to yslt
etherlab/entries_list.xslt
etherlab/entries_list.ysl2
etherlab/etherlab.py
--- a/etherlab/entries_list.xslt	Mon Sep 30 13:43:02 2013 +0200
+++ b/etherlab/entries_list.xslt	Wed Oct 02 10:46:18 2013 +0200
@@ -1,123 +1,1 @@
-<xsl:stylesheet version="1.0"
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-    xmlns:ns="entries_list_ns"
-    extension-element-prefixes="ns"
-    exclude-result-prefixes="ns">
-  <xsl:param name="min_index"/>
-  <xsl:param name="max_index"/>
-  <xsl:template match="Device">
-    <xsl:apply-templates select="Profile/Dictionary/Objects/Object"/>
-    <xsl:for-each select="RxPdo">
-      <xsl:call-template name="pdo_entries">
-        <xsl:with-param name="direction" select="'Receive'"/>
-      </xsl:call-template>
-    </xsl:for-each>
-    <xsl:for-each select="TxPdo">
-      <xsl:call-template name="pdo_entries">
-        <xsl:with-param name="direction" select="'Transmit'"/>
-      </xsl:call-template>
-    </xsl:for-each>
-  </xsl:template>
-  <xsl:template match="Object">
-    <xsl:variable name="index">
-      <xsl:value-of select="ns:HexDecValue(Index/text())"/>
-    </xsl:variable>
-    <xsl:variable name="entry_name">
-      <xsl:value-of select="ns:EntryName(Name)"/>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="$index &gt;= $min_index and $index &lt;= $max_index">
-        <xsl:variable name="datatype_name">
-          <xsl:value-of select="Type/text()"/>
-        </xsl:variable>
-        <xsl:choose>
-          <xsl:when test="ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]">
-            <xsl:apply-templates select="ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]">
-              <xsl:with-param name="index">
-                <xsl:value-of select="$index"/>
-              </xsl:with-param>
-              <xsl:with-param name="entry_name">
-                <xsl:value-of select="$entry_name"/>
-              </xsl:with-param>
-            </xsl:apply-templates>
-          </xsl:when>
-          <xsl:otherwise>
-            <ns:add_entry>
-              <Index><xsl:value-of select="$index"/></Index>
-              <SubIndex><xsl:text>0</xsl:text></SubIndex>
-              <Name><xsl:value-of select="$entry_name"/></Name>
-              <Type><xsl:value-of select="$datatype_name"/></Type>
-              <BitSize><xsl:value-of select="BitSize/text()"/></BitSize>
-              <Access><xsl:value-of select="Flags/Access/text()"/></Access>
-              <PDOMapping><xsl:value-of select="Flags/PdoMapping/text()"/></PDOMapping>
-            </ns:add_entry>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:when>
-    </xsl:choose>
-  </xsl:template>
-  <xsl:template match="DataType">
-    <xsl:param name="index"/>
-    <xsl:param name="entry_name"/>
-    <xsl:for-each select="SubItem">
-      <xsl:variable name="subentry_names">
-        <xsl:value-of select="DisplayName"/>
-        <Default><xsl:value-of select="Name/text()"/></Default>
-      </xsl:variable>
-      <ns:add_entry>
-        <Index><xsl:value-of select="$index"/></Index>
-        <SubIndex><xsl:value-of select="ns:HexDecValue(SubIdx/text())"/></SubIndex>
-        <Name>
-          <xsl:value-of select="$entry_name"/>
-          <xsl:text> - </xsl:text>
-          <xsl:value-of select="ns:EntryName($subentry_names)"/>
-        </Name>
-        <Type><xsl:value-of select="Type/text()"/></Type>
-        <BitSize><xsl:value-of select="BitSize/text()"/></BitSize>
-        <Access><xsl:value-of select="Flags/Access/text()"/></Access>
-        <PDOMapping><xsl:value-of select="Flags/PdoMapping/text()"/></PDOMapping>
-      </ns:add_entry>
-    </xsl:for-each>
-  </xsl:template>
-  <xsl:template name="pdo_entries">
-    <xsl:param name="direction"/>
-    <xsl:variable name="pdo_index">
-      <xsl:value-of select="ns:HexDecValue(Index/text())"/>
-    </xsl:variable>
-    <xsl:variable name="pdo_name">
-      <xsl:value-of select="ns:EntryName(Name)"/>
-    </xsl:variable>
-    <xsl:for-each select="Entry">
-	  <xsl:variable name="index">
-	    <xsl:value-of select="ns:HexDecValue(Index/text())"/>
-	  </xsl:variable>
-	  <xsl:choose>
-	    <xsl:when test="$index &gt;= $min_index and $index &lt;= $max_index">
-	      <ns:add_entry>
-            <Index><xsl:value-of select="$index"/></Index>
-            <SubIndex><xsl:value-of select="ns:HexDecValue(SubIndex/text())"/></SubIndex>
-            <Name><xsl:value-of select="ns:EntryName(Name)"/></Name>
-            <Type><xsl:value-of select="DataType/text()"/></Type>
-            <BitSize><xsl:value-of select="BitLen/text()"/></BitSize>
-            <xsl:choose>
-              <xsl:when test="$direction='Transmit'">
-                <Access><xsl:text>ro</xsl:text></Access>
-                <PDOMapping><xsl:text>T</xsl:text></PDOMapping>
-              </xsl:when>
-              <xsl:otherwise>
-                <Access><xsl:text>wo</xsl:text></Access>
-                <PDOMapping><xsl:text>R</xsl:text></PDOMapping>
-              </xsl:otherwise>
-            </xsl:choose>
-            <PDO>
-              <index><xsl:value-of select="$pdo_index"/></index>
-              <name><xsl:value-of select="$pdo_name"/></name>
-              <type><xsl:value-of select="$direction"/></type>
-            </PDO>
-          </ns:add_entry>
-	    </xsl:when>
-	  </xsl:choose>
-    </xsl:for-each>
-  </xsl:template>
-  <xsl:template match="text()"/>
-</xsl:stylesheet>
\ No newline at end of file
+<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" extension-element-prefixes="ns" xmlns:yml="http://fdik.org/yml" xmlns:set="http://exslt.org/sets" version="1.0" xmlns:ns="entries_list_ns" exclude-result-prefixes="ns" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml"/><xsl:variable name="space" select="'                                                                                                                                                                                                        '"/><xsl:param name="autoindent" select="4"/><xsl:param name="min_index"/><xsl:param name="max_index"/><xsl:template match="text()"><xsl:param name="_indent" select="0"/></xsl:template><xsl:template match="Device"><xsl:param name="_indent" select="0"/><xsl:apply-templates select="Profile/Dictionary/Objects/Object"><xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/></xsl:apply-templates><xsl:for-each select="RxPdo"><xsl:call-template name="pdo_entries"><xsl:with-param name="direction" select="'Receive'"/></xsl:call-template></xsl:for-each><xsl:for-each select="TxPdo"><xsl:call-template name="pdo_entries"><xsl:with-param name="direction" select="'Transmit'"/></xsl:call-template></xsl:for-each></xsl:template><xsl:template match="Object"><xsl:param name="_indent" select="0"/><xsl:variable name="index"><xsl:value-of select="ns:HexDecValue(Index/text())"/></xsl:variable><xsl:variable name="entry_name"><xsl:value-of select="ns:EntryName(Name)"/></xsl:variable><xsl:choose><xsl:when test="$index &gt;= $min_index and $index &lt;= $max_index"><xsl:variable name="datatype_name"><xsl:value-of select="Type/text()"/></xsl:variable><xsl:choose><xsl:when test="ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]"><xsl:apply-templates select="ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]"><xsl:with-param name="_indent" select="$_indent + (1) * $autoindent"/><xsl:with-param name="index"><xsl:value-of select="$index"/></xsl:with-param><xsl:with-param name="entry_name"><xsl:value-of select="$entry_name"/></xsl:with-param></xsl:apply-templates></xsl:when><xsl:otherwise><xsl:variable name="subindex"><xsl:text>0</xsl:text></xsl:variable><xsl:variable name="entry"><xsl:value-of select="ns:AddEntry($index, $subindex, $entry_name, $datatype_name, BitSize/text(), Flags/Access/text(), Flags/PdoMapping/text())"/></xsl:variable></xsl:otherwise></xsl:choose></xsl:when></xsl:choose></xsl:template><xsl:template match="DataType"><xsl:param name="_indent" select="0"/><xsl:param name="index"/><xsl:param name="entry_name"/><xsl:for-each select="SubItem"><xsl:variable name="subindex"><xsl:value-of select="ns:HexDecValue(SubIdx/text())"/></xsl:variable><xsl:variable name="subentry_name"><xsl:value-of select="$entry_name"/><xsl:text> - </xsl:text><xsl:value-of select="ns:EntryName(DisplayName, Name/text())"/></xsl:variable><xsl:variable name="entry"><xsl:value-of select="ns:AddEntry($index, $subindex, $subentry_name, Type/text(), BitSize/text(), Flags/Access/text(), Flags/PdoMapping/text())"/></xsl:variable></xsl:for-each></xsl:template><xsl:template name="pdo_entries"><xsl:param name="_indent" select="0"/><xsl:param name="direction"/><xsl:variable name="pdo_index"><xsl:value-of select="ns:HexDecValue(Index/text())"/></xsl:variable><xsl:variable name="pdo_name"><xsl:value-of select="ns:EntryName(Name)"/></xsl:variable><xsl:for-each select="Entry"><xsl:variable name="index"><xsl:value-of select="ns:HexDecValue(Index/text())"/></xsl:variable><xsl:choose><xsl:when test="$index &gt;= $min_index and $index &lt;= $max_index"><xsl:variable name="subindex"><xsl:value-of select="ns:HexDecValue(SubIndex/text())"/></xsl:variable><xsl:variable name="subentry_name"><xsl:value-of select="ns:EntryName(Name)"/></xsl:variable><xsl:variable name="access"><xsl:choose><xsl:when test="$direction='Transmit'"><xsl:text>ro</xsl:text></xsl:when><xsl:otherwise><xsl:text>wo</xsl:text></xsl:otherwise></xsl:choose></xsl:variable><xsl:variable name="pdo_mapping"><xsl:choose><xsl:when test="$direction='Transmit'"><xsl:text>T</xsl:text></xsl:when><xsl:otherwise><xsl:text>R</xsl:text></xsl:otherwise></xsl:choose></xsl:variable><xsl:variable name="entry"><xsl:value-of select="ns:AddEntry($index, $subindex, $subentry_name, DataType/text(), BitLen/text(), $access, $pdo_mapping, $pdo_index, $pdo_name, $direction)"/></xsl:variable></xsl:when></xsl:choose></xsl:for-each></xsl:template></xsl:stylesheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/entries_list.ysl2	Wed Oct 02 10:46:18 2013 +0200
@@ -0,0 +1,86 @@
+include yslt.yml2
+estylesheet xmlns:ns="entries_list_ns" 
+            extension-element-prefixes="ns" 
+            exclude-result-prefixes="ns" {
+    
+    param "min_index";
+    param "max_index";
+    
+    template "text()";
+    
+    template "Device" {
+        apply "Profile/Dictionary/Objects/Object";
+        foreach "RxPdo" {
+            call "pdo_entries" with "direction", "'Receive'";
+        }
+        foreach "TxPdo" {
+            call "pdo_entries" with "direction", "'Transmit'";
+        }
+    }
+    
+    template "Object" {
+        variable "index" > «ns:HexDecValue(Index/text())»
+        variable "entry_name" > «ns:EntryName(Name)»
+        choose {
+            when "$index >= $min_index and $index <= $max_index" {
+                variable "datatype_name" > «Type/text()»
+                choose {
+                    when "ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]" {
+                        apply "ancestor::Dictionary/child::DataTypes/DataType[Name/text()=$datatype_name][SubItem]" {
+                            with "index" > «$index»
+                            with "entry_name" > «$entry_name»
+                        }
+                    }
+                    otherwise {
+                        variable "subindex" > 0
+                        variable "entry" {
+                            > «ns:AddEntry($index, $subindex, $entry_name, $datatype_name, BitSize/text(), Flags/Access/text(), Flags/PdoMapping/text())»
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    template "DataType" {
+        param "index";
+        param "entry_name";
+        foreach "SubItem" {
+            variable "subindex" > «ns:HexDecValue(SubIdx/text())»
+            variable "subentry_name" > «$entry_name» - «ns:EntryName(DisplayName, Name/text())»
+            variable "entry" {
+                > «ns:AddEntry($index, $subindex, $subentry_name, Type/text(), BitSize/text(), Flags/Access/text(), Flags/PdoMapping/text())»
+            }
+        }
+    }
+    
+    function "pdo_entries" {
+        param "direction";
+        variable "pdo_index" > «ns:HexDecValue(Index/text())»
+        variable "pdo_name" > «ns:EntryName(Name)»
+        foreach "Entry" {
+            variable "index" > «ns:HexDecValue(Index/text())»
+            choose {
+                when "$index >= $min_index and $index <= $max_index" {
+                    variable "subindex" > «ns:HexDecValue(SubIndex/text())»
+                    variable "subentry_name" > «ns:EntryName(Name)»
+                    variable "access" {
+                        choose {
+                            when "$direction='Transmit'" > ro
+                            otherwise > wo
+                        }
+                    }
+                    variable "pdo_mapping" {
+                        choose {
+                            when "$direction='Transmit'" > T
+                            otherwise > R
+                        }
+                    }
+                    variable "entry" {
+                        > «ns:AddEntry($index, $subindex, $subentry_name, DataType/text(), BitLen/text(), $access, $pdo_mapping, $pdo_index, $pdo_name, $direction)»
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
--- a/etherlab/etherlab.py	Mon Sep 30 13:43:02 2013 +0200
+++ b/etherlab/etherlab.py	Wed Oct 02 10:46:18 2013 +0200
@@ -22,60 +22,44 @@
 EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
 EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath)
 
-def extract_param(el):
-    if el.tag == "Index":
-        return "#x%4.4X" % int(el.text)
-    elif el.tag == "BitSize":
-        if el.text is None:
-            return 0
-        return int(el.text)
-    elif el.tag == "PDOMapping":
-        if el.text is None:
-            return ""
-        return el.text.upper()
-    if el.text is None:
-        return ""
-    return el.text
-
-def extract_pdo_infos(pdo_infos):
-    return {
-        pdo_infos.tag + " " + el.tag: extract_param(el)
-        for el in pdo_infos}
-
-def HexDecValue(ctxt, values):
-    return str(ExtractHexDecValue(values[0]))
-
-def EntryName(ctxt, values):
-    default=None
-    names = []
-    for element in values:
-        if element.tag == "Default":
-            default = element.text
-        else:
-            names.append(element)
-    return ExtractName(names, default)
-
-class AddEntry(etree.XSLTExtension):
+def HexDecValue(context, *args):
+    return str(ExtractHexDecValue(args[0][0]))
+
+def EntryName(context, *args):
+    return ExtractName(args[0], 
+        args[1][0] if len(args) > 1 else None)
+
+ENTRY_INFOS_KEYS = [
+    ("Index", lambda x: "#x%4.4X" % int(x), "#x0000"),
+    ("SubIndex", str, "0"),
+    ("Name", str, ""),
+    ("Type", str, ""),
+    ("BitSize", int, 0),
+    ("Access", str, ""),
+    ("PDOMapping", str, ""),
+    ("PDO index", str, ""),
+    ("PDO name", str, ""),
+    ("PDO type", str, "")]
+
+class EntryListFactory:
 
     def __init__(self, entries):
-        etree.XSLTExtension.__init__(self)
         self.Entries = entries
     
-    def execute(self, context, self_node, input_node, output_parent):
-        infos = etree.Element('entry_infos')
-        self.process_children(context, infos)
-        index, subindex = map(
-            lambda x: int(infos.find(x).text),
-            ["Index", "SubIndex"])
+    def AddEntry(self, context, *args):
+        index, subindex = map(lambda x: int(x[0]), args[:2])
         new_entry_infos = {
-            el.tag: extract_param(el)
-            for el in infos if el.tag != "PDO"}
+            key: translate(arg[0]) if len(arg) > 0 else default
+            for (key, translate, default), arg
+            in zip(ENTRY_INFOS_KEYS, args)}
+        
         if (index, subindex) != (0, 0):
             entry_infos = self.Entries.get((index, subindex))
             if entry_infos is not None:
-                PDO_infos = infos.find("PDO")
-                if PDO_infos is not None:
-                    entry_infos.update(extract_pdo_infos(PDO_infos))
+                for param in ["PDO index", "PDO name", "PDO type"]:
+                    value = new_entry_infos.get(param)
+                    if value is not None:
+                        entry_infos[param] = value
             else:
                 self.Entries[(index, subindex)] = new_entry_infos
 
@@ -100,9 +84,11 @@
     def GetEntriesList(self, limits=None):
         entries = {}
         
+        factory = EntryListFactory(entries)
+        
         entries_list_xslt_tree = etree.XSLT(
             entries_list_xslt, extensions = {
-                ("entries_list_ns", "add_entry"): AddEntry(entries),
+                ("entries_list_ns", "AddEntry"): factory.AddEntry,
                 ("entries_list_ns", "HexDecValue"): HexDecValue,
                 ("entries_list_ns", "EntryName"): EntryName})
         entries_list_xslt_tree(self, **dict(zip(