Создание динамичных 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.
