<?xml version="1.0" encoding="UTF-8"?>
<!--FDT XSL transformation for Modbus protocol V1.0-->
<!--This XSL transformation defines the transformation of an XML document with Modbus specific parameters to a protocol independent -->
<!--XML document as it is required in FDT for the device identification and the scan -->


<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:str="http://xsltsl.org/string" xmlns:ident="x-schema:DTMIdentSchema.xml" xmlns:fdt="x-schema:FDTDataTypesSchema.xml" xmlns:scanident="x-schema:DTMScanIdentSchema.xml" xmlns:devident="x-schema:DTMDeviceTypeIdentSchema.xml" xmlns:modbusdevice="x-schema:FDTModbusDeviceTypeIdentSchema.xml" xmlns:modbusident="x-schema:FDTModbusIdentSchema.xml" xmlns:modbusscan="x-schema:FDTModbusScanIdentSchema.xml" xmlns:mb="x-schema:FDTModbusAddressSchema.xml" exclude-result-prefixes="str modbusdevice modbusident modbusscan mb">
	<!-- Definition of transformation output format -->
	<xsl:output method="xml" indent="no" encoding="UTF-8"/>
	<xsl:variable name="FileVersion" select="1.0"/>
	<!-- select root element FDT -->
	<xsl:template match="/">
		
			<!-- check if the XML document which shall be transfomed contains the information -->
			<!-- of a device identification or of a bus scan -->
			<xsl:apply-templates select="//modbusscan:ScanIdentifications"/>
			<xsl:apply-templates select="//modbusdevice:DeviceIdentifications"/>
		
	</xsl:template>
	<!-- the XML document contains the information for a device identification -->
	<xsl:template match="modbusdevice:DeviceIdentifications">

		<xsl:element name="devident:FDT">
		    <xsl:element name="devident:DeviceIdentifications">
                <xsl:apply-templates select="modbusdevice:DeviceIdentification"/>
		    </xsl:element>
		</xsl:element>
	</xsl:template>
    
	<!-- the XML document contains the information of a bus scan -->
	<xsl:template match="modbusscan:ScanIdentifications">
		<xsl:element name="scanident:FDT">
		    <xsl:element name="scanident:ScanIdentifications">
			    <xsl:attribute name="fdt:busCategory"><xsl:value-of select="./@fdt:busCategory"/></xsl:attribute>
			    <xsl:attribute name="resultState"><xsl:value-of select="./@resultState"/></xsl:attribute>
			    <xsl:apply-templates select="modbusscan:ScanIdentification"/>
		    </xsl:element>
		</xsl:element>
	</xsl:template>
    
    
	<!-- *****************************************   transformation of the bus scan information ************************************************-->
	<xsl:template match="modbusscan:ScanIdentification">
		<xsl:element name="scanident:ScanIdentification">
			<xsl:apply-templates select="./fdt:CommunicationError"/>
            
		    <!-- used bus protocol -->
    		<xsl:element name="scanident:IdBusProtocol">
	    		<xsl:attribute name="ident:protocolSpecificName"><xsl:text>Modbus</xsl:text></xsl:attribute>
		    	<xsl:attribute name="ident:value"><xsl:value-of select="modbusscan:IdBusProtocol/@modbusident:protocolName"/></xsl:attribute>
    		</xsl:element>
        
	    	<!-- bus protocol version -->
		    <xsl:element name="scanident:IdBusProtocolVersion">
                <xsl:attribute name="ident:protocolSpecificName"><xsl:text>not applicable</xsl:text></xsl:attribute>
    		</xsl:element>
        
	    	<!-- Modbus specific addressing depending on the physical layer -->
	    	<!-- Check if ModbusSerial element exists -->
	    	<xsl:apply-templates select=".//mb:ModbusSerial"/>
        
		    <!-- Check if ModbusTCP element exists -->
    		<xsl:apply-templates select=".//mb:ModbusTCP"/>
	    	<!-- device specific information received with ReadDeviceIdentification service -->
	    	<!-- mandatory identification objects specified in the Modbus application protocol specification (basic category) -->
        
		    <!-- Vendor Name -->
		    <xsl:element name="scanident:IdManufacturer">
			    <xsl:attribute name="ident:protocolSpecificName"><xsl:text>Vendor Name</xsl:text></xsl:attribute>
			    <xsl:attribute name="ident:value"><xsl:value-of select="modbusscan:IdManufacturer/@modbusident:vendorName"/></xsl:attribute>
		    </xsl:element>
        
		    <!-- Product Code -->
	    	<xsl:element name="scanident:IdTypeID">
		    	<xsl:attribute name="ident:protocolSpecificName"><xsl:text>Product Code</xsl:text></xsl:attribute>
			    <xsl:attribute name="ident:value"><xsl:value-of select="modbusscan:IdTypeID/@modbusident:productCode"/></xsl:attribute>
	    	</xsl:element>
        
		    <!-- MajorMinor Revision -->
		    <xsl:element name="scanident:IdSoftwareRevision">
			    <xsl:attribute name="ident:protocolSpecificName"><xsl:text>MajorMinorRevision</xsl:text></xsl:attribute>
			    <xsl:attribute name="ident:value"><xsl:value-of select="modbusscan:IdSoftwareRevision/@modbusident:majorMinorRevision"/></xsl:attribute>
		    </xsl:element>
        
	    	<!-- not applicable elements -->
		    <xsl:element name="scanident:IdHardwareRevision">
			    <xsl:attribute name="ident:protocolSpecificName"><xsl:text>not applicable</xsl:text></xsl:attribute>
	    	</xsl:element>
        
		    <xsl:element name="scanident:IdDeviceTag">
			    <xsl:attribute name="ident:protocolSpecificName"><xsl:text>not applicable</xsl:text></xsl:attribute>
		    </xsl:element>
        
		    <xsl:element name="scanident:IdSerialNumber">
			    <xsl:attribute name="ident:protocolSpecificName"><xsl:text>not applicable</xsl:text></xsl:attribute>
		    </xsl:element>
        
		    <!-- optional identification objects specified in the Modbus application protocol specification (regular category) -->
		    <xsl:element name="scanident:IdValues">
			    <xsl:apply-templates select="./modbusscan:IdValues"/>
		    </xsl:element>
        </xsl:element>
	</xsl:template>
    
    <!-- template for fdt:CommunicationError element -->
	<xsl:template match="fdt:CommunicationError">
	   <xsl:copy-of select="."/>
	</xsl:template>
    
	<!-- get address for Modbus Serial Line -->
	<xsl:template match="mb:ModbusSerial">
		<xsl:element name="scanident:IdAddress">
			<xsl:attribute name="ident:protocolSpecificName"><xsl:text>ModbusSerial</xsl:text></xsl:attribute>
			<xsl:attribute name="ident:value"><xsl:value-of select="@slaveAddress"/></xsl:attribute>
		</xsl:element>
	</xsl:template>
    
	<!-- get address for ModbusTCP -->
	<xsl:template match="mb:ModbusTCP">
		<xsl:element name="scanident:IdAddress">
			<xsl:attribute name="ident:protocolSpecificName"><xsl:text>ModbusTCP</xsl:text></xsl:attribute>
			<xsl:attribute name="ident:value"><xsl:value-of select="@tcpAddress"/></xsl:attribute>
		</xsl:element>
	</xsl:template>
    
	<!--check if optional identification objects are  provided (regular category) -->
	<xsl:template match="modbusscan:IdValues">
		<xsl:apply-templates select="./modbusscan:IdValue"/>
	</xsl:template>
    
	<!-- transformation of  optional identification objects (regular category) -->
	<xsl:template match="modbusscan:IdValue">
		<xsl:element name="scanident:IdValue">
			<xsl:call-template name="genScanName">
				<xsl:with-param name="name" select="@modbusident:name"/>
			</xsl:call-template>
			<xsl:call-template name="genScanMatch">
				<xsl:with-param name="value" select="@modbusident:value"/>
			</xsl:call-template>
			<xsl:call-template name="genScanProtocolSpecificName">
				<xsl:with-param name="protocolSpecificName" select="@modbusident:protocolSpecificName"/>
			</xsl:call-template>
		</xsl:element>
	</xsl:template>
    
	<xsl:template name="genScanName">
        <xsl:param name="name"/>
		<xsl:if test="$name">
			<xsl:attribute name="ident:name"><xsl:value-of select="$name"/></xsl:attribute>
		</xsl:if>
	</xsl:template>
    
	<xsl:template name="genScanMatch">
		<xsl:param name = "value"/>
		<xsl:if test = "$value">
			<xsl:attribute name = "ident:value">
				<xsl:value-of select = "$value"/>
			</xsl:attribute>
		</xsl:if>
	</xsl:template>
    
	<xsl:template name="genScanProtocolSpecificName">
		<xsl:param name="protocolSpecificName"/>
		<xsl:if test="$protocolSpecificName">
			<xsl:attribute name="ident:protocolSpecificName"><xsl:value-of select="$protocolSpecificName"/></xsl:attribute>
		</xsl:if>
	</xsl:template>
    
    
	<!-- *****************************************  transformation of the device identification information ************************************************-->
	<xsl:template match="modbusdevice:DeviceIdentification">
		<xsl:element name="devident:DeviceIdentification">
			<xsl:attribute name="ident:idDTMSupportLevel"><xsl:value-of select="@modbusident:idDTMSupportLevel"/></xsl:attribute>
			
            <!-- used bus protocol -->
			<xsl:element name="devident:IdBusProtocol">
				<xsl:attribute name="ident:protocolSpecificName"><xsl:text>Modbus</xsl:text></xsl:attribute>
				<xsl:attribute name="ident:value"><xsl:value-of select="modbusdevice:IdBusProtocol/@modbusident:protocolName"/></xsl:attribute>
			</xsl:element>
			
            <!-- bus protocol version -->
			<xsl:element name="devident:IdBusProtocolVersion">
                <xsl:attribute name="ident:protocolSpecificName"><xsl:text>not applicable</xsl:text></xsl:attribute>
			</xsl:element>
			
            <!-- device specific information received with ReadDeviceIdentification service -->
			<!-- mandatory identification objects specified in the Modbus application protocol specification (basic category) -->
			
            <xsl:apply-templates select="modbusdevice:IdManufacturer"/>
            <xsl:apply-templates select="modbusdevice:IdTypeID"/>
            <xsl:apply-templates select="modbusdevice:IdSoftwareRevision"/>
			
            <!-- not applicable element -->
			<xsl:element name="devident:IdHardwareRevision">
				<xsl:attribute name="ident:protocolSpecificName"><xsl:text>not applicable</xsl:text></xsl:attribute>
			</xsl:element>
			
            <!-- optional identification objects specified in the Modbus application protocol specification (regular category) -->
			<xsl:element name="devident:IdValues">
				<xsl:apply-templates select="./modbusdevice:IdValues"/>
			</xsl:element>
		</xsl:element>
	</xsl:template>
    
    <!-- Vendor Name -->
    <xsl:template match="modbusdevice:IdManufacturer">
        <xsl:element name="devident:IdManufacturer">
			<xsl:attribute name="ident:protocolSpecificName"><xsl:text>Vendor Name</xsl:text></xsl:attribute>
			<xsl:attribute name="ident:value"><xsl:value-of select="@modbusident:vendorName"/></xsl:attribute>
			<xsl:call-template name="genMatch">
			    <xsl:with-param select="modbusdevice:IdManufacturer" name="value" />
			</xsl:call-template>
        </xsl:element>
    </xsl:template>
    
    <!-- Product Code -->
    <xsl:template match="modbusdevice:IdTypeID">
		<xsl:element name="devident:IdTypeID">
            <xsl:attribute name="ident:protocolSpecificName"><xsl:text>Product Code</xsl:text></xsl:attribute>
            <xsl:attribute name="ident:value"><xsl:value-of select="@modbusident:productCode"/></xsl:attribute>
            <xsl:call-template name="genMatch" >
                <xsl:with-param select="modbusdevice:IdTypeID" name="value" />
            </xsl:call-template>
			</xsl:element>    
    </xsl:template>
    
    
    <!-- MajorMinor Revision -->
    <xsl:template match="modbusdevice:IdSoftwareRevision">
        <xsl:element name="devident:IdSoftwareRevision">
            <xsl:attribute name="ident:protocolSpecificName"><xsl:text>MajorMinorRevision</xsl:text></xsl:attribute>
            <xsl:attribute name="ident:value"><xsl:value-of select="@modbusident:majorMinorRevision"/></xsl:attribute>
            <xsl:call-template name="genMatch">
                <xsl:with-param select="modbusdevice:IdSoftwareRevision" name="value" />
        </xsl:call-template>
        </xsl:element>
    </xsl:template>       
    
    
	<!--check if optional identification objects are  provided (regular category) -->
	<xsl:template match="modbusdevice:IdValues">
		<xsl:apply-templates select="./modbusdevice:IdValue"/>
	</xsl:template>
    
	<!-- transformation of  optional identification objects (regular category) -->
	<xsl:template match="modbusdevice:IdValue">
		<xsl:element name="devident:IdValue">
			<xsl:call-template name="genName">
				<xsl:with-param name="name" select="@modbusident:name"/>
			</xsl:call-template>
			<xsl:if test="@modbusident:value">
				<xsl:attribute name="ident:value"><xsl:value-of select="@modbusident:value"/></xsl:attribute>
			</xsl:if>
			<xsl:call-template name="genProtocolSpecificName">
				<xsl:with-param name="protocolSpecificName" select="@modbusident:protocolSpecificName"/>
			</xsl:call-template>            
			<xsl:call-template name="genMatch">
				<xsl:with-param select="modbusdevice:IdValue" name="value" />
			</xsl:call-template>
		</xsl:element>
	</xsl:template>
    
	<xsl:template name="genName">
		<xsl:param name="name"/>
		<xsl:if test="$name">
			<xsl:attribute name="ident:name"><xsl:value-of select="$name"/></xsl:attribute>
		</xsl:if>
	</xsl:template>
    
	<xsl:template name="genProtocolSpecificName">
		<xsl:param name="protocolSpecificName"/>
		<xsl:if test="$protocolSpecificName">
			<xsl:attribute name="ident:protocolSpecificName"><xsl:value-of select="$protocolSpecificName"/></xsl:attribute>
		</xsl:if>
	</xsl:template>
    
	<xsl:template name="genMatch">
		<xsl:param name="value"/>
            <xsl:apply-templates select="modbusident:RegExpr"/>
	</xsl:template>
    
	<xsl:template match="modbusident:RegExpr">
		<!-- copy pattern info -->		
		<xsl:call-template name="genPattern">
			<xsl:with-param name="match" select="@match"/>
			<xsl:with-param name="nomatch" select="@nomatch"/>
		</xsl:call-template>
	</xsl:template>
    
	<!-- generation of the pattern for the regular expressions -->
	<!-- These regular expressions can be used by a DTM in order to define a range of supported physical device types  -->
	<xsl:template name="genPattern">
		<xsl:param name="match"/>
		<xsl:param name="nomatch"/>
		<xsl:choose>
			<xsl:when test="$match">
				<xsl:element name="ident:RegExpr">
					<xsl:attribute name="match"><xsl:value-of select="$match"/></xsl:attribute>
					<xsl:if test="$nomatch">
						<xsl:attribute name="nomatch"><xsl:value-of select="$nomatch"/></xsl:attribute>
					</xsl:if>
				</xsl:element>
			</xsl:when>
			<xsl:when test="$nomatch">
				<xsl:element name="ident:RegExpr">
					<xsl:attribute name="nomatch"><xsl:value-of select="$nomatch"/></xsl:attribute>
					<xsl:if test="$match">
						<xsl:attribute name="match"><xsl:value-of select="$match"/></xsl:attribute>
					</xsl:if>
				</xsl:element>
			</xsl:when>
		</xsl:choose>
	</xsl:template>
</xsl:transform>
