Создание динамичных ProDataSet
Если вы заранее не знаете, какую получите схему, то AVM может создать динамический ProDataSet во время выполнения. Динамические ProDataSet используются для того, чтобы обеспечить соответствие входящей схеме XML.
Предположим, что вы обмениваетесь данными с клиентом только один или два раза в год. Вы хотите обмениваться различными видами данных каждый раз, в зависимости от текущих требований бизнеса. Вы не знаете, какая схема будет использоваться, поэтому вы не можете создать ProDataSet заранее.
Например, предположим, что вы получаете счёт от коммунальной компании раз в месяц. Местные налоги и сборы могут меняться с течением времени. Описания этих налогов и сборов также могут измениться. Кроме того, количество полей в определении счета-фактуры может измениться. В этом случае AVM может создать ProDataSet динамически во время выполнения, чтобы соответствовать входящей XML-схеме.
Для чтения схемы XML в динамический ProDataSet необходимо:
- Определить дескриптор для набора данных: CREATE hDset AS HANDLE.
- Создать набор данных: CREATE DATASET hDset.
- Использовать один из методов READ-XML или READ-XMLSCHEMA.
Здесь создаётся пустой набор данных без какой-либо структуры. Затем во время выполнения одного из XML-методов, во время чтения XML-схемы AVM динамически создаст ProDataSet.
Далее приведён пример процедуры, которая делает следующее:
- Создаёт динамический ProDataSet без структуры.
- Читает схему XML для создания структуры ProDataSet.
- Заполняет набор данных данными из файла XML.
- Показывает схему и данные для демонстрации правильно созданного и заполненного набора данных информацией из файлов .xsd и .xml.
/* populate_dynamic_dataset.p */ /* Include parameters definitions for read/write XML methods */ {parameterVarDefs.i} DEFINE VARIABLE htab AS HANDLE NO-UNDO. DEFINE VARIABLE hdset AS HANDLE NO-UNDO. DEFINE VARIABLE hbuf AS HANDLE NO-UNDO. DEFINE VARIABLE hrel AS HANDLE NO-UNDO. DEFINE VARIABLE hq AS HANDLE NO-UNDO. DEFINE VARIABLE i AS INTEGER NO-UNDO. DEFINE VARIABLE j AS INTEGER NO-UNDO. DEFINE VARIABLE k AS INTEGER NO-UNDO. DEFINE VARIABLE lReturn AS LOGICAL NO-UNDO. /* the dataset is created in the clear state (no schema yet) */ CREATE DATASET hdset. CREATE QUERY hq. ASSIGN cSourceType = "FILE" cSourceName = "dsOrderOrderline.xsd" lOverrideDefaultMapping = ? cfieldTypeMapping = ? cverifySchemaMode = ?. DO TRANSACTION: /* Read the XML schema from the .xsd schema file to create the definition for the dataset */ lReturn = hdset:READ-XMLSCHEMA(cSourceType, cSourceName, lOverrideDefaultMapping, cFieldTypeMapping, cVerifySchemaMode). IF lReturn = FALSE THEN DO: MESSAGE "dsOrderOrderline READ-XMLSCHEMA failed!" . LEAVE. END. ASSIGN cSourceType = "FILE" cSourceName = "dsorderorderline.xml" cReadMode = ? cSchemaLocation = ? lOverrideDefaultMapping = FALSE cFieldTypeMapping = ? cVerifySchemaMode = ?. /* READ-XML will populate dataset from xml file */ lReturn = hdset:READ-XML(cSourceType, cSourceName, cReadMode, cSchemaLocation, lOverrideDefaultMapping, cFieldTypeMapping, cVerifySchemaMode). IF lReturn = FALSE THEN DO: MESSAGE "dsOrderOrderline READ-XML failed!" . LEAVE. END. END. /* transaction */ /* Remaining code displays the schema and the data to show the dataset was properly created and populated from information in both the .xsd and the .xml files */ /* General Info */ MESSAGE "num-buffers: " hdset:NUM-BUFFERS "name: " hdset:NAME SKIP "nspace-info: " hdset:NAMESPACE-URI hdset:NAMESPACE-PREFIX VIEW-AS ALERT-BOX. /* Info about data-relations */ MESSAGE "num-relations: " hdset:NUM-RELATIONS VIEW-AS ALERT-BOX. DO i = 1 TO hdset:NUM-RELATIONS: hrel = hdset:GET-RELATION(i). MESSAGE "rel name: " hrel:NAME SKIP "reposition: " hrel:REPOSITION SKIP "nested: " hrel:NESTED SKIP "where-str: " hrel:WHERE-STRING SKIP "parent: " hrel:PARENT-BUFFER:NAME SKIP "child: " hrel:CHILD-BUFFER:NAME SKIP "rel-fields: " hrel:RELATION-FIELDS VIEW-AS ALERT-BOX. END. /* Info about each temp-table */ DO j = 1 TO hdset:NUM-BUFFERS: hbuf = hdset:GET-BUFFER-HANDLE(j). MESSAGE "buf name: " hbuf:NAME VIEW-AS ALERT-BOX. DO i = 1 TO hbuf:NUM-FIELDS: MESSAGE "name:" hbuf:BUFFER-FIELD(i):NAME " type:" hbuf:BUFFER-FIELD(i):DATA-TYPE " xmltype:" hbuf:BUFFER-FIELD(i):XML-DATA-TYPE " xmlnodetype:" hbuf:BUFFER-FIELD(i):XML-NODE-TYPE " initial:" hbuf:BUFFER-FIELD(i):INITIAL " format:" hbuf:BUFFER-FIELD(i):FORMAT " help:" hbuf:BUFFER-FIELD(i):HELP VIEW-AS ALERT-BOX. END. END. /* The data in each temp-table */ CREATE QUERY hq. DO j = 1 TO hdset:NUM-BUFFERS: hbuf = hdset:GET-BUFFER-HANDLE(j). hq:SET-BUFFERS(hbuf). hq:QUERY-PREPARE("for each " + hbuf:NAME). hq:QUERY-OPEN. k = 0. DO WHILE hq:GET-NEXT(): k = k + 1. DO i = 1 TO hbuf:NUM-FIELDS: MESSAGE "PRODATASET DATA: " SKIP "BUFFER NAME : " hbuf:NAME SKIP " Field name : " hbuf:BUFFER-FIELD(i):NAME SKIP " Field value : " IF hbuf:BUFFER-FIELD(i):EXTENT > 0 THEN hbuf:BUFFER-FIELD(i):BUFFER-VALUE[1] ELSE hbuf:BUFFER-FIELD(i):BUFFER-VALUE VIEW-AS ALERT-BOX. IF i > 3 THEN LEAVE. /* skip the rest */ END. IF k > 1 THEN LEAVE. /* skip the rest */ END. END. DELETE OBJECT hq. DELETE OBJECT hdset. OUTPUT CLOSE.