Get Started with Analytixus

Follow these steps to set up Analytixus on your system and start accelerating your data projects.

Install prerequisites

Download and install the .NET Core 8 Runtime Framework.

Download Analytixus

Get the latest release from our Download page as a ZIP file.
Extract it into a folder of your choice, for example:
C:\Analytixus\App

Set up your project space

Inside your installation folder, create a subfolder called ProjectData. Each of your projects should have its own subfolder here.
C:\Analytixus\ProjectData

Run the application

simply start AnalytixusApp.exe.

Windows protected your PC

If Windows prevents the program from running with the following message, you can install the certificate File "Analytixus.cer" from the "Certificates" folder as a “trusted root certificate.” After that, the program should run without any warnings.

Option: Install SAP-Driver

SAP HANA Client

For SAP HANA access install the SAP HANA Client (x64).
👉 You need a User to download the Software

SAP Development Tools or direct hanaclient-latest-windows-x64.zip

SAP NCO 3.1 for .NET Core

For SAP ERP (ECC or S4) or SAP BW access download SAP Connector for Microsoft .NET 3.1 Compiled for .NET (formerly .NET Core).
👉 You need a User to download the Software

SAP Connector for Microsoft .NET or direct SAP Connector for Microsoft .NET 3.1.6.0 for Windows 64bit (x64)

After downloading, unzip the files. Then copy all files with the “.dll” extension to the Analytixus app folder (where the AnalytixusApp.exe is located).

Next Steps in Analytixus

After installing and starting Analytixus, here’s how you can set up your first project and begin working with metadata.

Create your first project

Click the Database-Symbol and choose the folder C:\Analytixus\ProjectData or an other one. Name your project MyFirstProject.

Add a source

Inside the project, you will see an empty Sources folder. Right-click it and choose New Source — select from CSV, Oracle, PostgreSQL, SQL Server, Databricks, SAP SuccessFactors, and more.

In my example I use the Wide World Importers sample database, which is installed on an Azure SQL Database.

Configure connection & metadata

Enter the connection details and filters in the dialog. – Use Test to validate the connection. – Use Save to store the Metadata as so called unsupervised Metadata. The individual metadata files for each object are displayed in the tree view and can be opened. Since this is raw metadata and manual modification until the next metadata update is pointless, we call it unsupervised metadata. When saved, this XML-based metadata was converted into a compact and editable form –> DnAML (Data and Analytics Markup Language).

DnAML (Data and Analytics Markup Language) is a domain-specific, JSON-like metadata format used for the semantic description and processing of data sources, structures, and transformations in data analytics solutions. It enables the centralized definition and management of data models across the entire data processing chain—from raw data ingestion to analytical provisioning.
In the metadata lifecycle, unsupervised metadata are transformed into a DnAML model, representing the second stage of the process.

Open the Model (DnAML) to see which metadata has been read in. Update the XML metadata preview below and Save it with the button.

The DnAML model is transformed into a unified XML format and stored as supervised metadata.
The structured and validated metadata description serves as the foundation for subsequent code generation with XSLT-Scripts or LLM-Automation. The corresponding file “Metadata.xml” is stored in the project folder.

Analytixus will create two files in your project folder:

  • Metadata.xml — full metadata in XML (supervised Metadata)
  • Model.dnaml — optimized, compressed model

Organize your architecture

Create subfolders like Bronze, Silver, and Gold to follow a medallion architecture. This is to better organize the scripts for your framework. You can also create any other folder to store reusable scripts or similar files later.

Generate code with transformations

Right-click a folder (e.g. Bronze) and add a new XSLTX Transformation. – Use XPath to select metadata from unsupervised Meatadata (Metadata.xml). – Below define how code should be generated with your XSLT script.

In Metadata and Preview you can see which metadata has been selected, what the generated code looks like and whether new metadata can be created

XSLT transformation vs. XSLTX transformation:

XSLT transformation are standard XSLT script templates that are suitable for outsourcing reusable elements. For example, data type conversions can be outsourced and reintegrated into other XSLTX transformations. XSLTX transformations are also XSLT script templates, but with the difference that they are provided with supervised metadata by the build process to generate code.

BronzeStore.xsltx

Metadata-XPath:
//Source/Object[@ObjectType='Table' and (count(Column[@IsPK!='0'])!=0 or count(Column[@IsBK!='0'])!=0)]
XSLT-Script:
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="2.0" exclude-result-prefixes="msxsl">
  <xsl:output method="text" indent="yes" />
  <xsl:include href="..\Common\DataType.xslt" />
  <xsl:include href="..\Common\CommonFunctions.xslt" />  
  <xsl:template match="Object">
    <xsl:variable name="TableName">
      <xsl:text>`</xsl:text>
      <xsl:value-of select="@SourceName" />
      <xsl:text>`.`Store_</xsl:text>
        <xsl:call-template name="replace">
            <xsl:with-param name="inputString" select="@ObjectName" />
            <xsl:with-param name="searchChar" select="'/'" />
            <xsl:with-param name="replaceChar" select="''" />
        </xsl:call-template>
      <xsl:text>`</xsl:text>
    </xsl:variable>
    <xsl:variable name="PKConstraintName">
      <xsl:text>`PK_</xsl:text>
      <xsl:value-of select="@SourceName" />
      <xsl:text>_Store_</xsl:text>
        <xsl:call-template name="replace">
            <xsl:with-param name="inputString" select="@ObjectName" />
            <xsl:with-param name="searchChar" select="'/'" />
            <xsl:with-param name="replaceChar" select="''" />
        </xsl:call-template>
      <xsl:text>`</xsl:text>
    </xsl:variable>    
    <xsl:variable name="Primarykeys">
      <xsl:value-of select="count(Column[@IsPK!='0'])!=0" />
    </xsl:variable>
    <xsl:variable name="Businesskeys">
      <xsl:value-of select="count(Column[@IsBK!='0'])!=0" />
    </xsl:variable>
    <xsl:text>CREATE OR REPLACE TABLE </xsl:text>
    <xsl:value-of select="$TableName" />
    <xsl:text>
(</xsl:text>
    <!-- Select Field and generate column entry -->
    <xsl:text>
	-- Techical Fields
	`DWH_DEF_DATE` TIMESTAMP NOT NULL /*IsTechnical*/
	,`DWH_LOAD_ID` INT NOT NULL /*IsTechnical*/
	,`DWH_RECORD_ID` BIGINT GENERATED ALWAYS AS IDENTITY NOT NULL /*IsTechnical*/
	,`DWH_SOURCE_ID` INT NOT NULL /*IsTechnical*/
	,`DWH_SOURCETABLE` STRING /*IsTechnical*/</xsl:text>
    <xsl:text>
	-- Custom Fields</xsl:text>
    <xsl:for-each select="Column[@IsTechnical!='1' or not(@IsTechnical)]">
      <xsl:sort select="@Ordinal" data-type="number" />
      <xsl:text>
	, `</xsl:text>
      <xsl:value-of select="@ColumnName" />
      <xsl:text>` </xsl:text>
      <xsl:call-template name="DataType" />
      <xsl:if test="$Businesskeys='false' and @IsPK='1'">
        <xsl:text> /*IsBK*/</xsl:text>
      </xsl:if>
      <xsl:if test="$Primarykeys='false' and @IsBK='1'">
        <xsl:text> /*IsBK*/</xsl:text>
      </xsl:if>
    </xsl:for-each>
    <xsl:if test="$Primarykeys='true'">
      <xsl:text>
	-- PK-CONSTRAINTs</xsl:text>
      <xsl:text>
	,CONSTRAINT </xsl:text>
      <xsl:value-of select="$PKConstraintName" />
      <xsl:text> PRIMARY KEY (DWH_RECORD_ID)</xsl:text>
    </xsl:if>
    <xsl:text>
);
         </xsl:text>
  </xsl:template>
</xsl:stylesheet>

CommonFunctions.xslt

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" />
    <xsl:template name="replace">
        <xsl:param name="inputString" />
        <xsl:param name="searchChar" />
        <xsl:param name="replaceChar" />
        <!-- Check if the search character is contained in the string -->
        <xsl:choose>
            <xsl:when test="contains($inputString, $searchChar)">
                <!-- Replace the first occurrence and call the template recursively -->
                <xsl:value-of select="substring-before($inputString, $searchChar)" />
                <xsl:value-of select="$replaceChar" />
                <xsl:call-template name="replace">
                    <xsl:with-param name="inputString" select="substring-after($inputString, $searchChar)" />
                    <xsl:with-param name="searchChar" select="$searchChar" />
                    <xsl:with-param name="replaceChar" select="$replaceChar" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <!-- No more search characters, print the rest of the string -->
                <xsl:value-of select="$inputString" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

DataType.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:template name="DataType">
      <xsl:text />
      <xsl:choose>
         <xsl:when test="@DataType ='NVARCHAR'">
            <xsl:text>STRING</xsl:text>
         </xsl:when>
         <xsl:when test="@DataType ='VARCHAR' or @DataType ='UNIQUEIDENTIFIER'">
            <xsl:text>STRING</xsl:text>
         </xsl:when>
         <xsl:when test="@DataType ='BINARY'">
            <xsl:text>VARIANT</xsl:text>
         </xsl:when>
         <xsl:when test="@DataType ='VARBINARY' or @DataType ='GEOGRAPHY'">
            <xsl:text>VARIANT</xsl:text>
         </xsl:when>
         <xsl:when test="@DataType ='DATETIME2' or @DataType ='DATETIME'">
            <xsl:text>timestamp</xsl:text>
         </xsl:when>
         <xsl:when test="@DataType ='BIT'">
            <xsl:text>boolean</xsl:text>
         </xsl:when>
         <xsl:when test="@DataType = 'NUMERIC' or @DataType = 'DECIMAL' or @DataType = 'decimal'">
            <xsl:text>DECIMAL</xsl:text>
            <xsl:if test="@NumericPrecision and @NumericScale">
            	<xsl:text>(</xsl:text>
            	<xsl:value-of select="@NumericPrecision" />
            	<xsl:text>,</xsl:text>
            	<xsl:value-of select="@NumericScale" />
            	<xsl:text>)</xsl:text>
            </xsl:if>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="@DataType" />
         </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
         <xsl:when test="@IsNullable='1'">
            <xsl:text />
         </xsl:when>
         <xsl:when test="@IsNullable='0'">
            <xsl:text> NOT NULL</xsl:text>
         </xsl:when>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

Build the Code

Start the build process via the context menu to generate the code and any metadata in bulk and save it in separate files.

Customize Model.DnaML

After the build, check the Model (DnAML) to see what new metadata was detected. You can make changes here and save them as supervised Metadata.

Iterate towards the Gold layer

Work step by step through Bronze → Silver → Gold, enriching your metadata along the way. Anything not auto-generated can be extended directly in the Model (DnAML) — e.g. relations, keys, or calculation expressions.

Everything else can be found in the help.

👉 ChatGPT is very helpful when creating XSLT scripts.