Tool An xslt stylesheet to document BA Classes

Here's an xslt file to transform BA library xml files into documentation similar to the one offered by Warwound's xml2bb
However, as Warwound's does not work well for classes (for me anyway), I have coded this xslt 2.0 sheet to do just that.
You can check the result here of such transformation here.

B4X:
<?xml version="1.0" encoding="UTF-8"?>
<!--Author: Cimperia-->
<!--Date:25/11/2015-->
<!--Version: 1.0-->
<!--Stylesheet to transform BA(A/J)'s libraries XML files-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"
   xmlns:foo="http://www.SolutionsBuilder.com">

   <xsl:output method="text"/>

   <xsl:template match="/">
     <!--Retrieve and list the library dependencies-->
     <xsl:if test="count(/node()/dependsOn) &gt; 0">
       <xsl:text>[B]Dependencies[/B]</xsl:text>
       <xsl:text>[LIST]</xsl:text>
       <xsl:for-each select="/node()/dependsOn">
         <xsl:apply-templates select="."/>
       </xsl:for-each>
       <xsl:text>&#xa;[/LIST]</xsl:text>
     </xsl:if>
     <!--Process all classes-->
     <xsl:apply-templates select="/node()/class"/>
   </xsl:template>

   <!--
     Process a dependsOn element
   -->
   <xsl:template match="dependsOn">
     <xsl:text>&#xa;[*]</xsl:text>
     <xsl:value-of select="."/>
   </xsl:template>

   <!--
     Process a class node
   -->
   <xsl:template match="class">
     <xsl:variable name="classType">
       <xsl:choose>
         <xsl:when test="attribute::b4a_type">
           <xsl:value-of select="@b4a_type"/>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select="'Class'"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:variable>

     <xsl:text>&#xa;[B]</xsl:text>
     <xsl:value-of select="shortname"/>
     <xsl:text> (</xsl:text>
     <xsl:value-of select="$classType"/>
     <xsl:text>)[/B]</xsl:text>
     <!--Process Class Properties-->
     <xsl:if test="count(current()/property) &gt; 0">
       <xsl:variable name="DesignerMethods">
         <xsl:value-of select="string-join(method/name/attribute::DesignerName, ',')"/>
       </xsl:variable>
       <xsl:text>&#xa;[B]Properties:[/B]&#xa;[LIST]</xsl:text>
       <xsl:for-each select="current()/property">
         <xsl:call-template name="Node">
           <xsl:with-param name="DesignerNames" as="xs:string" select="$DesignerMethods"/>
         </xsl:call-template>
       </xsl:for-each>
       <xsl:text>&#xa;[/LIST]</xsl:text>
     </xsl:if>
     <!--Process Class Fields-->
     <xsl:if test="count(current()/field) &gt; 0">
       <xsl:variable name="DesignerMethods">
         <xsl:value-of select="string-join(method/name/attribute::DesignerName, ',')"/>
       </xsl:variable>
       <xsl:text>&#xa;[B]Fields:[/B]&#xa;[LIST]</xsl:text>
       <xsl:for-each select="current()/field">
         <xsl:call-template name="Node">
           <xsl:with-param name="DesignerNames" as="xs:string" select="$DesignerMethods"/>
         </xsl:call-template>
       </xsl:for-each>
       <xsl:text>&#xa;[/LIST]</xsl:text>
     </xsl:if>
     <!--Process Class Methods-->
     <xsl:if test="count(current()/method) &gt; 0">
       <xsl:text>&#xa;[B]Methods:[/B]&#xa;[LIST]</xsl:text>
       <xsl:for-each select="current()/method">
         <xsl:call-template name="method">
         </xsl:call-template>
       </xsl:for-each>
       <xsl:text>&#xa;[/LIST]</xsl:text>
     </xsl:if>
   </xsl:template>

   <!--
     Process Field or Property node.
     If the attribute DesignerName exists, retrieve this value,
     otherwise gets the name text.
     Retrieve the return type.
   -->
   <xsl:template name="Node">
     <xsl:param name="DesignerNames" as="xs:string" required="yes"/>
     <!--Store and format return type value, if it exists-->
     <xsl:variable name="returnType">
       <xsl:value-of select="foo:ShortObjectName(returntype, '.', '\.+')"/>
     </xsl:variable>
     <!--Process field's elements-->
     <xsl:for-each select="child::*">
       <xsl:variable name="champ" select="name()" as="xs:string"/>
       <xsl:choose>
         <xsl:when test="$champ = 'name'">
           <xsl:text>&#xa;[*]  </xsl:text>
           <xsl:call-template name="MethodName"/>
           <!--Add return type if exists-->
           <xsl:if test="string-length($returnType) &gt; 0">
             <xsl:text> [COLOR=blue]As[/COLOR] </xsl:text>
             <xsl:text>[COLOR=green]</xsl:text>
             <xsl:value-of select="$returnType"/>
             <xsl:text>[/COLOR]</xsl:text>
             <xsl:call-template name="IsMethodReadOnly">
               <xsl:with-param name="ClassMethods" as="xs:string"
                 select="$DesignerNames"/>
             </xsl:call-template>
           </xsl:if>
         </xsl:when>
         <xsl:when test="$champ = 'comment'">
           <xsl:text>&#xa;[I]</xsl:text>
           <xsl:value-of select="."/>
           <xsl:text>[/I]</xsl:text>
         </xsl:when>
       </xsl:choose>
     </xsl:for-each>
   </xsl:template>
   <!--End Field Node Processing-->

   <!--
     Process Method node.
     If the attribute DesignerName exists, retrieve this value,
     otherwise gets the name text.
     Retrieve parameters and their types as well as the return type.
   -->
   <xsl:template name="method">
     <!--     <xsl:param name="DesignerNames" as="xs:string" required="yes"/>-->
     <xsl:variable name="IsHidden">
       <xsl:call-template name="IsMethodHidden"/>
     </xsl:variable>
     <xsl:if test="$IsHidden = false()">
       <!--Store and format return type value, if it exists-->
       <xsl:variable name="returnType">
         <xsl:value-of select="foo:ShortObjectName(returntype, '.', '\.+')"/>
       </xsl:variable>
       <!--Store and format parameters values, if they exist-->
       <xsl:variable name="parameters">
         <xsl:for-each select="child::parameter">
           <xsl:variable name="type">
             <xsl:value-of select="foo:ShortObjectName(type, '.', '\.+')"/>
           </xsl:variable>
           <xsl:value-of select="name"/> [COLOR=blue]As[/COLOR] [COLOR=green]<xsl:value-of
             select="$type"/><xsl:text>[/COLOR]</xsl:text>
           <xsl:if test="position() != last()">, </xsl:if>
         </xsl:for-each>
       </xsl:variable>
       <!--Process method's elements-->
       <xsl:for-each select="child::*">
         <xsl:variable name="field" select="name()" as="xs:string"/>
         <xsl:choose>
           <xsl:when test="$field = 'name'">
             <xsl:text>&#xa;[*]  </xsl:text>
             <xsl:call-template name="MethodName"/>
             <!--Add parameters if exist-->
             <xsl:if test="string-length($parameters) &gt; 0">
               <xsl:text> (</xsl:text>
               <xsl:value-of select="$parameters"/>
               <xsl:text>)</xsl:text>
             </xsl:if>
             <!--Add return type if exists-->
             <xsl:if test="string-length($returnType) &gt; 0">
               <xsl:text> [COLOR=blue]As[/COLOR] </xsl:text>
               <xsl:text>[COLOR=green]</xsl:text>
               <xsl:value-of select="$returnType"/>
               <xsl:text>[/COLOR]</xsl:text>
               <!--               <xsl:call-template name="IsMethodReadOnly">
                 <xsl:with-param name="ClassMethods" as="xs:string"
                   select="$DesignerNames"/>
               </xsl:call-template>-->
             </xsl:if>
           </xsl:when>
           <xsl:when test="$field = 'comment'">
             <xsl:text>&#xa;[I]</xsl:text>
             <xsl:value-of select="."/>
             <xsl:text>[/I]</xsl:text>
           </xsl:when>
         </xsl:choose>
       </xsl:for-each>
     </xsl:if>
   </xsl:template>

   <!--
     Named template: MethodName
     Writes out method name
   -->
   <xsl:template name="MethodName">
     <xsl:choose>
       <xsl:when test="attribute::DesignerName">
         <xsl:value-of select="@DesignerName"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:value-of select="."/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:template>

   <!--
     Named template: IsMethodHidden
     Return true if method is hidden from b4(a/j) designer
   -->
   <xsl:template name="IsMethodHidden">
     <!--Process method's elements-->
     <xsl:for-each select="child::name">
       <xsl:sequence select="attribute::HideFromIDE and @HideFromIDE = 'true'"/>
     </xsl:for-each>
   </xsl:template>

   <!--
     Named template: IsMethodReadOnly
     If method starts with 'get' then check whether a 'set' equivalent exists.
     If not, write out 'read only'.
   -->
   <xsl:template name="IsMethodReadOnly">
     <xsl:param name="ClassMethods" as="xs:string" required="yes"/>
     <xsl:if test="attribute::DesignerName">
       <xsl:if test="contains($ClassMethods, concat('get',@DesignerName)) and not(contains($ClassMethods, concat('set',@DesignerName)))">
           <xsl:text> [I][read only][/I]</xsl:text>
       </xsl:if>
     </xsl:if>
   </xsl:template>

   <!--
     Return variable short name.
   -->
   <xsl:function name="foo:ShortObjectName">
     <xsl:param name="source" as="xs:string"/>
     <xsl:param name="delimiter" as="xs:string"/>
     <xsl:param name="pattern" as="xs:string"/>
     <xsl:choose>
       <xsl:when test="contains($source, $delimiter)">
         <xsl:variable name="tokens" select="tokenize($source, $pattern)"/>
         <xsl:value-of select="subsequence(reverse($tokens),1,1)"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:value-of select="$source"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:function>

</xsl:stylesheet>
 
Last edited:
Top