XPath-Beispiel mit XML-Schema

Mithilfe des Funktionsbausteins FB_DBRecordSelect oder FB_DBRecordArraySelect können XPath‑Kommandos abgesetzt und XML-Tags, XML-Subtags oder XML-Attribute aus einer beliebigen XML-Datei gelesen werden. Ist ein passendes XML-Schema für die zu lesende XML-Datei vorhanden, werden die Inhalte der Tags bzw. Attribute in die entsprechenden Datentypen konvertiert, so wie sie in dem Schema definiert sind.

Nähere Informationen zu XML-Schemas finden Sie hier: http://www.edition-w3.de/TR/2001/REC-xmlschema-0-20010502/

In diesem Beispiel werden mit dem FB_DBRecordArraySelect zwei unterschiedliche Subtags aus einer XML-Datei mit zugehörigem XML-Schema ausgelesen.

Download: TcDBSrv_InfoSysSamples.zip

XPath-Beispiel mit XML-Schema 1:

Verwendeter Datenbanktyp

XML

Kompatible Datenbanktypen

XML

Verwendete Funktionsbausteine

FB_DBRecordSelect

Einzubindende Bibliotheken

Tc2_Database, Tc2_System, Tc2_Standard, Tc2_Utilities

Download Dateiliste

TcDBSrv_InfoSysSamples.tszip, CurrentConfigDatabase.xml, PLC_Structs.xml, PLC_Structs.xsd

Beispiel XML-Datei (PLC_Structs.xml)

<?xml version = "1.0" encoding="utf-8" ?>
<Beckhoff_PLC>
  <PLC_Structs>
    <PLC_Struct Name="ST_TestStruct">
      <Struct Instance="1">
        <nINT64>123456789</nINT64>
        <nUINT16>1234</nUINT16>
        <rREAL64>1234.5678</rREAL64>
        <sSTRING>This is instance one of ST_TestStruct</sSTRING>
        <bBOOL>true</bBOOL>
        <nINT32>-100</nINT32>
      </Struct>
      <Struct Instance="2">
        <nINT64>234567890</nINT64>
        <nUINT16>2345</nUINT16>
        <rREAL64>234.56789</rREAL64>
        <sSTRING>This is instance two of ST_TestStruct</sSTRING>
        <bBOOL>false</bBOOL>
        <nINT32>-50</nINT32>
      </Struct>
      <Struct Instance="3">
        <nINT64>345678901</nINT64>
        <nUINT16>3456</nUINT16>
        <rREAL64>3456.78901</rREAL64>
        <sSTRING>This is instance three of ST_TestStruct</sSTRING>
        <bBOOL>true</bBOOL>
        <nINT32>-150</nINT32>
      </Struct>
    </PLC_Struct>
    <PLC_Struct Name="ST_TestStruct2">
      <Struct2 Instance="1">
        <sSTRING>This is instance one of ST_TestStruct2</sSTRING>
        <bBOOL>false</bBOOL>
        <nINT32>-88</nINT32>
      </Struct2>
      <Struct2 Instance="2">
        <sSTRING>This is instance two of ST_TestStruct2</sSTRING>
        <bBOOL>true</bBOOL>
        <nINT32>-9</nINT32>
      </Struct2>
    </PLC_Struct>
  </PLC_Structs>
</Beckhoff_PLC>

Zugehöriges XML-Schema (PLC_Structs.xsd)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Beckhoff_PLC">
    <xs:complexType >
      <xs:sequence >
        <xs:element name = "PLC_Structs">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs = "unbounded" name="PLC_Struct">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element minOccurs = "0" maxOccurs="unbounded" name="Struct">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name = "nINT64" type="xs:long" />
                          <xs:element name = "nUINT16" type="xs:unsignedShort" />
                          <xs:element name = "rREAL64" type="xs:double" />
                          <xs:element name = "sSTRING" type="xs:string" />
                          <xs:element name = "bBOOL" type="xs:boolean" />
                          <xs:element name = "nINT32" type="xs:int" />
                        </xs:sequence>
                        <xs:attribute name = "Instance" type="xs:unsignedByte" use="required" />
                      </xs:complexType>
                    </xs:element>
                    <xs:element minOccurs = "0" maxOccurs="unbounded" name="Struct2">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name = "sSTRING" type="xs:string" />
                          <xs:element name = "bBOOL" type="xs:boolean" />
                          <xs:element name = "nINT32" type="xs:int" />
                        </xs:sequence>
                        <xs:attribute name = "Instance" type="xs:unsignedByte" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name = "Name" type="xs:string" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Struktur1 ST_TestStruct

TYPE ST_TestStruct :
STRUCT
    nINT64 : T_LARGE_INTEGER;
    nUINT16: UINT;
    rREAL64: LREAL;
    sSTRING: T_MaxString;
    bBOOL  : BOOL;
    nINT32 : DINT;
END_STRUCT
END_TYPE 

Struktur2 ST_TestStruct2

TYPE ST_TestStruct2 :
STRUCT
    sSTRING: T_MaxString;
    bBOOL  : BOOL;
    nINT32 : DINT;
END_STRUCT
END_TYPE 

MAIN-Programm

PROGRAM MAIN
VAR
 nState                 : BYTE;

 R_TRIG1                : R_TRIG;
 bStartStop             : BOOL;

 sCmd                   : T_MaxString;

 FB_DBRecordArraySelect1: FB_DBRecordArraySelect;
 arrTestStruct          : ARRAY [0..3] OF ST_TestStruct;
 arrTestStruct2         : ARRAY [0..3] OF ST_TestStruct2;

 bBusy                  : BOOL;
 bError                 : BOOL;
 nErrID                 : UDINT;
 stSQLState             : ST_DBSQLError;

 nRecs1                 : UDINT;
 nRecs2                 : UDINT;
END_VAR 
R_TRIG1(CLK:=bStartStop);
IF R_TRIG1.Q THEN
 FB_DBRecordArraySelect1(bExecute:=FALSE);
 nState                 := 1;
END_IF
CASE nState OF
 0:(*Idle*)
 ;
 1:
 sCmd:='XPATH<SUBTAG>#/Beckhoff_PLC/PLC_Structs/PLC_Struct[@Name=$'ST_TestStruct$']/Struct';

 FB_DBRecordArraySelect1(
     sNetID            := ,
     hDBID             := 1,
     cbCmdSize         := SIZEOF(sCmd),
     pCmdAddr          := ADR(sCmd),
     nStartIndex       := 0,
     nRecordCount      := 4,
     cbRecordArraySize := SIZEOF(arrTestStruct),
     pDestAddr         := ADR(arrTestStruct),
     bExecute          := TRUE,
     tTimeout          := T#15s,
     bBusy              => bBusy,
     bError             => bError,
     nErrID             => nErrID,
     sSQLState          => stSQLState,
     nRecords           => nRecs1);

 IF NOT bBusy THEN
    FB_DBRecordArraySelect1(bExecute:=FALSE);
    IF NOT bError THEN
     nState            := 2;
    ELSE
     nState            := 255;
    END_IFEND_IF
 2:
 sCmd:='XPATH<SUBTAG>#Beckhoff_PLC/PLC_Structs/PLC_Struct[@Name=$'ST_TestStruct2$']/Struct2';

 FB_DBRecordArraySelect1(
     sNetID            := ,
     hDBID             := 1,
     cbCmdSize         := SIZEOF(sCmd),
     pCmdAddr          := ADR(sCmd),
     nStartIndex       := 0,
     nRecordCount      := 4,
     cbRecordArraySize := SIZEOF(arrTestStruct2),
     pDestAddr         := ADR(arrTestStruct2),
     bExecute          := TRUE,
     tTimeout          := T#15s,
     bBusy              => bBusy,
     bError             => bError,
     nErrID             => nErrID,
     sSQLState          => stSQLState,
     nRecords           => nRecs2);

 IF NOT bBusy THEN
    FB_DBRecordArraySelect1(bExecute:=FALSE);
    IF NOT bError THEN
     nState            := 0;
    ELSE
     nState            := 255;
    END_IFEND_IF
 255: (* Error Step*)
 ;
END_CASE 

Mit einer positiven Flanke an der Toggle-Variable „bStartStop“ wird das Auslesen gestartet.

XPath-Beispiel mit XML-Schema 2:

Voraussetzungen

Entwicklungsumgebung

Zielplattform

Einzubindende SPS Bibliotheken

TwinCAT v3.0.0

PC oder CX (x86)

Tc2_Database