<?xml version="1.0" encoding="UTF-8"?>
<!--FDT XSL transformation for Modbus protocol V0.4-->
<!--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:mbdevice="x-schema:FDTModbusDeviceTypeIdentSchema.xml" xmlns:mbident="x-schema:FDTModbusIdentSchema.xml" xmlns:mbscan="x-schema:FDTModbusScanIdentSchema.xml" xmlns:mb="x-schema:FDTModbusAddressSchema.xml" exclude-result-prefixes="str mbdevice mbident mbscan mb">
	<!-- Definition of transformation output format -->
	<xsl:output method="xml" indent="no" encoding="UTF-8"/>
	<xsl:variable name="FileVersion" select="0.4"/>
	<!-- 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="//mbscan:ScanIdentifications"/>
			<xsl:apply-templates select="//mbdevice:DeviceIdentifications"/>
		
	</xsl:template>
	<!-- the XML document contains the information for a device identification -->
	<xsl:template match="mbdevice:DeviceIdentifications">

		<xsl:element name="devident:FDT">
		    <xsl:element name="devident:DeviceIdentifications">
                <xsl:apply-templates select="mbdevice:DeviceIdentification"/>
		    </xsl:element>
		</xsl:element>
	</xsl:template>
    
	<!-- the XML document contains the information of a bus scan -->
	<xsl:template match="mbscan: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="mbscan:ScanIdentification"/>
		    </xsl:element>
		</xsl:element>
	</xsl:template>
    
    
	<!-- *****************************************   transformation of the bus scan information ************************************************-->
	<xsl:template match="mbscan: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="mbscan:IdBusProtocol/@mbident: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="mbscan:IdManufacturer/@mbident: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="mbscan:IdTypeID/@mbident: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="mbscan:IdSoftwareRevision/@mbident: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="./mbscan: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="mbscan:IdValues">
		<xsl:apply-templates select="./mbscan:IdValue"/>
	</xsl:template>
    
	<!-- transformation of  optional identification objects (regular category) -->
	<xsl:template match="mbscan:IdValue">
		<xsl:element name="scanident:IdValue">
			<xsl:call-template name="genScanName">
				<xsl:with-param name="name" select="@mbident:name"/>
			</xsl:call-template>
			<xsl:call-template name="genScanMatch">
				<xsl:with-param name="value" select="@mbident:value"/>
			</xsl:call-template>
			<xsl:call-template name="genScanProtocolSpecificName">
				<xsl:with-param name="protocolSpecificName" select="@mbident: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="mbdevice:DeviceIdentification">
		<xsl:element name="devident:DeviceIdentification">
			<xsl:attribute name="ident:idDTMSupportLevel"><xsl:value-of select="@mbident: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="mbdevice:IdBusProtocol/@mbident: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="mbdevice:IdManufacturer"/>
            <xsl:apply-templates select="mbdevice:IdTypeID"/>
            <xsl:apply-templates select="mbdevice: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="./mbdevice:IdValues"/>
			</xsl:element>
		</xsl:element>
	</xsl:template>
    
    <!-- Vendor Name -->
    <xsl:template match="mbdevice: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="@mbident:vendorName"/></xsl:attribute>
			<xsl:call-template name="genMatch">
			    <xsl:with-param select="mbdevice:IdManufacturer" name="value" />
			</xsl:call-template>
        </xsl:element>
    </xsl:template>
    
    <!-- Product Code -->
    <xsl:template match="mbdevice: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="@mbident:productCode"/></xsl:attribute>
            <xsl:call-template name="genMatch" >
                <xsl:with-param select="mbdevice:IdTypeID" name="value" />
            </xsl:call-template>
			</xsl:element>    
    </xsl:template>
    
    
    <!-- MajorMinor Revision -->
    <xsl:template match="mbdevice: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="@mbident:majorMinorRevision"/></xsl:attribute>
            <xsl:call-template name="genMatch">
                <xsl:with-param select="mbdevice:IdSoftwareRevision" name="value" />
        </xsl:call-template>
        </xsl:element>
    </xsl:template>       
    
    
	<!--check if optional identification objects are  provided (regular category) -->
	<xsl:template match="mbdevice:IdValues">
		<xsl:apply-templates select="./mbdevice:IdValue"/>
	</xsl:template>
    
	<!-- transformation of  optional identification objects (regular category) -->
	<xsl:template match="mbdevice:IdValue">
		<xsl:element name="devident:IdValue">
			<xsl:call-template name="genName">
				<xsl:with-param name="name" select="@mbident:name"/>
			</xsl:call-template>
			<xsl:if test="@mbident:value">
				<xsl:attribute name="ident:value"><xsl:value-of select="@mbident:value"/></xsl:attribute>
			</xsl:if>
			<xsl:call-template name="genProtocolSpecificName">
				<xsl:with-param name="protocolSpecificName" select="@mbident:protocolSpecificName"/>
			</xsl:call-template>            
			<xsl:call-template name="genMatch">
				<xsl:with-param select="mbdevice: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="mbident:RegExpr"/>
	</xsl:template>
    
	<xsl:template match="mbident: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>
