XPath sample to illustrate the different SELECT types

The function block FB_DBRecordArraySelect/FB_DBRecordSelect can be used to issue XPath commands and read XML tags from any XML file. This sample illustrates reading of different entries from XML files via the TwinCAT Database Server. Individual tags, subtags and reading of attributes is supported, and these are displayed.

Download: TcDBSrv_InfoSysSamples.zip

XPath sample to illustrate the different SELECT types 1:

Database type used

XML

Compatible database types

XML

Function blocks used

FB_DBRecordArraySelect

Libraries to be integrated

Tc2_Database, Tc2_System, Tc2_Standard, Tc2_Utilities

Download file list

TcDBSrv_InfoSysSamples.tszip

Sample XML file (XMLFactoryXY.xml)

<?xmlversion="1.0" encoding="utf-8" ?>
<Factory_XY>
<Name>Sample Factory XY</Name>
<Factory_Info>
<Street>Samplestreet 25</Street>
<City>33415 Verl</City>
<Country>Germany</Country>
<Office_Count>1</Office_Count>
<Employe_Count>6</Employe_Count>
<Manager>Max Mustermann</Manager>
</Factory_Info>
<Employees>
<Employeeid="10001" name="Julia Kingston" department="Development" position="Worker" hired="2001-08-01" />
<Employeeid="10002" name="Jens Marx" department="Import" position="Worker" hired="2003-08-01" />
<Employeeid="10003" name="Justus Kaiser" department="Export" position="Worker" hired="2003-08-01" />
<Employeeid="10004" name="Marc Klein" department="Production" position="Worker" hired="2005-08-01" />
<Employeeid="10005" name="Matt Bloomberg" department="Production" position="Worker" hired="2005-08-01" />
<Employeeid="10006" name="Frida Hundt" department="Production" position="Worker" hired="2010-08-01" />
</Employees>
</Factory_XY>

ST_FactoryInfo structure

TYPEST_FactoryInfo :
STRUCT
 sStreet       : T_MaxString;
 sCity         : T_MaxString;
 sCountry      : T_MaxString;
 sOffice_Count : T_MaxString;
 sEmploye_Count: T_MaxString;
 sManager      : T_MaxString;
END_STRUCT
END_TYPE

ST_Employee structure

TYPEST_Employee :
STRUCT
 sID          : T_MaxString;
 sName        : T_MaxString;
 sDepartment  : T_MaxString;
 sPosition    : T_MaxString;
 sHired       : T_MaxString;
END_STRUCT
END_TYPE

MAIN program

PROGRAM MAIN 
VAR
     bSTART    : BOOL;
     R_TRIG1   : R_TRIG;
     
     nState    : INT;

     sXPath    : T_MaxString;
     
     fbDBRecordArraySelect : FB_DBRecordArraySelect;
     
     bBusy_ReadFactoryName : BOOL;
     bError_ReadFactoryName: BOOL;
     nErrID_ReadFactoryName: UDINT;
     
     bBusy_ReadFactoryInfo : BOOL;
     bError_ReadFactoryInfo: BOOL;
     nErrID_ReadFactoryInfo: UDINT;
     
     bBusy_ReadEmployee    : BOOL;
     bError_ReadEmployee   : BOOL;
     nErrID_ReadEmployee   : UDINT;
     
     stSQLState            : ST_DBSQLError;
     
     sFactoryName          : T_MaxString;
     stFactoryInfo         : ST_FactoryInfo;
     aEmployees            : ARRAY [1..10] OF ST_Employee;
END_VAR 
R_TRIG1(CLK:=bSTART);
IF R_TRIG1.Q THEN
     bSTART:=FALSE;
     fbDBRecordArraySelect(bExecute:=FALSE);
     nState:=1;
END_IF
CASE nState OF
     0://IDLE
         ;
     1://Read Factory Name
         sXPath:= 'XPATH#Factory_XY/Name';
         fbDBRecordArraySelect(
             sNetID           := , 
             hDBID            := 7, 
             pCmdAddr         := ADR(sXPath), 
             cbCmdSize        := SIZEOF(sXPath), 
             nStartIndex      := 0, 
             nRecordCount     := 1, 
             pDestAddr        := ADR(sFactoryName), 
             cbRecordArraySize:= SIZEOF(sFactoryName), 
             bExecute         := TRUE, 
             tTimeout         := T#15S, 
             bBusy             => bBusy_ReadFactoryName, 
             bError            => bError_ReadFactoryName, 
             nErrID            => nErrID_ReadFactoryName, 
             sSQLState         => stSQLState, 
             nRecords          => );
             
         IF NOT bBusy_ReadFactoryName THEN
             fbDBRecordArraySelect(bExecute:=FALSE);
             IF NOT bError_ReadFactoryName THEN
                 nState        :=2;
             ELSE
                 nState        :=255;
             END_IFEND_IF
     2://Read Factory Info
         sXPath                 := 'XPATH#Factory_XY/Factory_Info';
         fbDBRecordArraySelect(
             sNetID            := , 
             hDBID             := 7, 
             pCmdAddr          := ADR(sXPath), 
             cbCmdSize         := SIZEOF(sXPath), 
             nStartIndex       := 0, 
             nRecordCount      := 1, 
             pDestAddr         := ADR(stFactoryInfo), 
             cbRecordArraySize := SIZEOF(stFactoryInfo), 
             bExecute          := TRUE, 
             tTimeout          := T#15S, 
             bBusy              => bBusy_ReadFactoryInfo, 
             bError             => bError_ReadFactoryInfo, 
             nErrID             => nErrID_ReadFactoryInfo, 
             sSQLState          => stSQLState, 
             nRecords           => );
             
         IF NOT bBusy_ReadFactoryInfo THEN
             fbDBRecordArraySelect(bExecute:=FALSE);
             IF NOT bError_ReadFactoryInfo THEN
                 nState         :=3;
             ELSE
                 nState         :=255;
             END_IF
         END_IF
     3://Read Employees
         sXPath                  := 'XPATH#Factory_XY/Employees/Employee';
         fbDBRecordArraySelect(
             sNetID             := , 
             hDBID              := 7, 
             pCmdAddr           := ADR(sXPath), 
             cbCmdSize          := SIZEOF(sXPath), 
             nStartIndex        := 0, 
             nRecordCount       := 10, 
             pDestAddr          := ADR(aEmployees), 
             cbRecordArraySize  := SIZEOF(aEmployees), 
             bExecute           := TRUE, 
             tTimeout           := T#15S, 
             bBusy               => bBusy_ReadEmployee, 
             bError              => bError_ReadEmployee, 
             nErrID              => nErrID_ReadEmployee, 
             sSQLState           => stSQLState, 
             nRecords            => );
             
         IF NOT bBusy_ReadEmployee THEN
             fbDBRecordArraySelect(bExecute:=FALSE);
             IF NOT bError_ReadEmployee THEN
                 nState          :=0;
             ELSE
                 nState          :=255;
             END_IFEND_IF
     255://Error State
         ;
END_CASE

A positive edge at the variable "bStart" triggers issuing of the XPath commands and reading of the individual elements from the XML file. The results will then be in the variables "sFactoryName", "stFactoryInfo" and "aEmployees".

Requirements

Development environment

Target platform

PLC libraries to be linked

TwinCAT v3.0.0

PC or CX (x86)

Tc2_Database