TEMP-TABLE, PRODATASET ИМПОРТ-ЭКСПОРТ ДАННЫХ XML
В OpenEdge ABL имеется возможность осуществлять как экспорт данных временных таблиц в формат XML, так и импорт данных из формата XML во временную таблицу.
Рассматривая объявление временных таблиц мы умолчали о нескольких опциях, отвечающих за импорт-экспорт данных этих таблиц в формат XML, о которых самое время рассказать.
XML ОПЦИИ TEMP-TABLE И DATASET
Для примера, объявим две временные таблицы, содержащие информацию по физическим лицам. Первая таблица будет содержать основную информацию о лицах, а во вторую мы запишем контактные данные этих лиц, такие как домашний телефон, мобильный телефон и e-mail.
DEF VAR lResult AS LOGICAL NO-UNDO.
DEF TEMP-TABLE tt-persons XML-NODE-NAME "Person"
FIELD ID AS INTEGER XML-NODE-TYPE "hidden"
FIELD fio AS CHAR XML-NODE-NAME "personName"
FIELD birthday AS DATE XML-NODE-NAME "birthday"
FIELD town AS CHAR XML-NODE-NAME "personTown"
.
DEF TEMP-TABLE tt-contacts XML-NODE-NAME "Contacts"
FIELD ID AS INTEGER XML-NODE-TYPE "hidden"
FIELD phone AS CHAR XML-NODE-NAME "homePhone"
FIELD e-mail AS CHAR XML-NODE-NAME "eMail"
FIELD mob-phone AS CHAR XML-NODE-NAME "mobilePhone"
.
Объединим наши таблицы в DataSet:
DEF DATASET dataPersons XML-NODE-NAME "dataPerson"
FOR tt-persons, tt-contacts
DATA-RELATION FOR tt-persons, tt-contacts
RELATION-FIELDS (ID, ID) NESTED.
При объявлении временных таблиц и DataSet мы использовали опции XML-NODE-NAME и XML-NODE-TYPE, которые определяют наименование элементов таблицы и их тип в структуре XML.
- XML-NODE-NAME - определяет наименование элемента в структуре XML. Если для элемента таблицы не определен XML-NODE-NAME, то по умолчанию наименование соответствующего элемента в структуре XML будет точно таким же, как и наименование этого элемента таблицы.
- XML-NODE-TYPE - значение CHAR типа определяет тип представления элемента таблицы в структуре XML и может принимать следующие значения:
- ELEMENT - элемент таблицы представляется тегом в XML (по умолчанию);
- ATTRIBUTE - элемент таблицы представляется атрибутом элемента XML;
- TEXT - элемент таблицы представляется текстовым элементом XML;
- HIDDEN - элемент таблицы не будет представлен в структуре XML.
Опция NAMESPACE-URI позволяет указать URI пространства имен, определяемого для всех элементов таблицы, а опция NAMESPACE-PREFIX определяет его префикс.
Опция NESTED в DATA-RELATION объявления DataSet-а, указывает на то, что в структуре XML, строки дочерней таблицы будут вложены в строки родительской таблицы.
XML-СХЕМЫ, МЕТОДЫ WRITE-XMLSCHEMA И READ-XMLSCHEMA
Для формирования XML-схем, соответствующих нашим таблицам и DATASET-у, применяется метод WRITE-XMLSCHEMA.
WRITE-XMLSCHEMA (target-type, target,
[, formatted [, encoding [, min-xmlschema
[, omit-initial-values ]]]])
target-type - определяет тип приемника данных, в который осуществляется экспорт XML-схемы. Может принимать следующие значения:
- FILE - запись в файл;
- STREAM - запись в поток;
- MEMPTR - запись в переменную MEMPTR типа;
- HANDLE - указатель приемника;
- LONGCHAR - запись в переменную, или поле таблицы LONGCHAR типа;
target - определяет приемник, в который осуществляется запись XML-схемы для source-type = FILE это путь к XML файлу, для LONGCHAR - идентификатор переменной.
formatted - логическое значение, определяющее представление XML-схемы. При значении TRUE, схема будет представлена в структурированном виде с применением переноса строки и табуляции, а при FALSE или ? - единой строкой.
encoding - определяет кодировку XML-схемы.
min-xmlschema - логическое значение, определяющее формат XML-схемы. При значение TRUE формат XML-схемы будет минимизированным, при FALSE - развернутым. Значением по умолчанию является FALSE.
omit-initial-values - логическое значение, исключающее из выгрузки в XML полей таблицы содержащие их начальные значения. По умолчанию равно FALSE, т.е. в XML выгружаются все поля таблицы.
lResult = TEMP-TABLE tt-persons:WRITE-XMLSCHEMA("FILE",
"./Person.xsd",
TRUE,
"windows-1251",
TRUE).
В результате будет сформирован файл Person.xsd:
<?xml version="1.0" encoding="windows-1251"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="" xmlns:prodata="urn:schemas-progress-com:xml-prodata:0001">
<xsd:element name="Person" prodata:proTempTable="true" prodata:tableName="tt-persons">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="PersonRow" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="personName" type="xsd:string" nillable="true" prodata:fieldName="fio"/>
<xsd:element name="birthday" type="xsd:date" nillable="true" prodata:fieldName="birthday"/>
<xsd:element name="personTown" type="xsd:string" nillable="true" prodata:fieldName="town"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Для большей наглядности представим данную схему в графическом виде.
Примером такого XML-файла является:
<?xml version="1.0" encoding="windows-1251"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersonRow>
<ID>1</ID>
<personName>Иванов Иван Иванович</personName>
<birthday>1979-10-26</birthday>
<personTown>Москва</personTown>
</PersonRow>
<PersonRow>
<ID>2</ID>
<personName>Николаев Николай Николаевич</personName>
<birthday>1965-08-22</birthday>
<personTown>Нижний Новгород</personTown>
</PersonRow>
<PersonRow>
<ID>3</ID>
<personName>Сергеев Сергей Сергеевич</personName>
<birthday>1981-04-11</birthday>
<personTown>Самара</personTown>
</PersonRow>
<Person>
Как мы видим, корневым элементом XML является <Person>, наименование которого мы определили в опции XML-NODE-NAME таблицы. Если бы мы не определили XML-NODE-NAME для таблицы, то по умолчанию, корневой элемент имел бы наименование самой таблицы, т.е. в нашем случае было бы <tt-persons>. Каждая запись в таблице представляет собой элемент <PersonRow>, наименование которого, формируется AVM автоматически путем приписывания Row к XML-NODE-NAME таблицы. Поля таблицы представлены тегами с наименованиями, определенными соответствующими для них опциями XML-NODE-NAME.
Сформируем аналогичную XML-схему для DATASET-а:
lResult = DATASET dataPersons:WRITE-XMLSCHEMA("FILE",
"./PersonInfo.xsd",
TRUE,
"windows-1251",
TRUE).
<?xml version="1.0" encoding="windows-1251"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="" xmlns:prodata="urn:schemas-progress-com:xml-prodata:0001">
<xsd:element name="dataPerson" prodata:proDataSet="true" prodata:datasetName="dataPersons">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Person" minOccurs="0" maxOccurs="unbounded" prodata:tableName="tt-persons">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="personName" type="xsd:string" nillable="true" prodata:fieldName="fio"/>
<xsd:element name="birthday" type="xsd:date" nillable="true" prodata:fieldName="birthday"/>
<xsd:element name="personTown" type="xsd:string" nillable="true" prodata:fieldName="town"/>
<xsd:element name="Contacts" minOccurs="0" maxOccurs="unbounded" prodata:tableName="tt-contacts">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="homePhone" type="xsd:string" nillable="true" prodata:fieldName="phone"/>
<xsd:element name="eMail" type="xsd:string" nillable="true" prodata:fieldName="e-mail"/>
<xsd:element name="mobilePhone" type="xsd:string" nillable="true" prodata:fieldName="mob-phone"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:annotation>
<xsd:appinfo>
<prodata:relation name="RELATION1" prodata:nested="true" prodata:parent="tt-persons" prodata:child="tt-contacts" prodata:relationFields="ID,ID"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:schema>
Пример такого файла:
<?xml version="1.0" encoding="windows-1251"?>
<dataPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Person>
<personName>Иванов Иван Иванович</personName>
<birthday>1979-10-26</birthday>
<personTown>Москва</personTown>
<Contacts>
<homePhone>8(495)111-22-33</homePhone>
<eMail>Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.</eMail>
<mobilePhone>111111111111</mobilePhone>
</Contacts>
</Person>
<Person>
<personName>Николаев Николай Николаевич</personName>
<birthday>1965-08-22</birthday>
<personTown>Нижний Новгород</personTown>
<Contacts>
<homePhone>8(495)222-33-44</homePhone>
<eMail>Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.</eMail>
<mobilePhone>22222222222</mobilePhone>
</Contacts>
</Person>
<Person>
<personName>Сергеев Сергей Сергеевич</personName>
<birthday>1981-04-11</birthday>
<personTown>Самара</personTown>
<Contacts>
<homePhone>8(495)333-44-55</homePhone>
<eMail>Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.</eMail>
<mobilePhone>33333333333</mobilePhone>
</Contacts>
</Person>
</dataPerson>
В OpenEdge возможен и обратный процесс, а именно формирование объектов на основе существующей XML-схемы.
Метод READ-XMLSCHEMA позволяет создавать динамические объекты (temp-table и ProDataSet) на основе XML-схем. Применительно к статическим объектам, данный метод позволяет осуществлять их верификацию, т.е. определять их соответствие заданной XML-схеме.
READ-XMLSCHEMA (source-type,
source-type,
override-default-mapping
[, field-type-mapping [, verify-schema-mode]])
source-type - значение CHAR типа, определяет тип источника XML-схемы и может принимать следующие значения:
- FILE - чтение из файла;
- MEMPTR - чтение из переменной MEMPTR типа;
- HANDLE - указатель источника;
- LONGCHAR - чтение из переменной или поля таблицы LONGCHAR типа;
source - определяет источник XML-схемы. Так для source-type имеющего значение "FILE" это путь к XML-файлу, для LONGCHAR - идентификатор переменной или поля таблицы.
override-default-mapping -
field-type-mapping -
verify-schema-mode - значение CHAR типа определяющее режим верификации, осуществляемой на основе XML-схемы, указанной в schema-location или в структуре XML. Может принимать следующие значения:
- IGNOR - верификация не осуществляется.
- LOOSE - осуществляет сверку элементов temp-table или ProDataSet с соответствующими им элементами XML-схемы. Данный режим допускает несовпадение структур temp-table/ProDataSet и XML-схемы. Элементы temp-table или ProDataSet, для которых отсутствуют соответствующие элементы в XML-схеме - игнорируются.
- STRICT - жесткий режим верификации, при котором структура temp-table или ProDataSet должна полностью соответствовать XML-схеме.
В OpenEdge имеется утилита bproxsdto4gl, вызываемая из командной строки и осуществляющая формирования иклюд-файлов с объявлениями статических temp-table и ProDataSet, сформированных на основе файла XML-схемы.
bproxsdto4gl
[-h]
|
{xml-schema-filename
[-output {output-directory-name | filename}]
[-element element-name]
[-overridemapping]
[-fieldtypemapping {field-mapping-file | string}]
[-noint64]
}
-h - выводит справку по утилите.
xml-schema-filename - абсолютный или относительный путь файла XML-схемы.
-output { output-directory | filename } - определяет наименование и расположение формируемого инклюд-файла с объявлениями temp-table и DATASET. По умолчанию, инклюд-файл формируется в каталоге XML-схемы и имеет схожее с ним наименование.
-element element-name - определяет элемент верхнего уровня в XML-схеме с которого необходимо формировать объявления объектов (temp-table и DATASET).
-overridemapping -
-fieldtypemapping { field-mapping-file | field-mapping-string } -
-noint64 - осуществляет конвертация xsd:long типа в тип DECIMAL вместо INT64. Данная конвертация актуальна для версий OpenEdge ниже 10.1B, так как данные версии не поддерживают формат INT64.
ИМПОРТ ДАННЫХ ИЗ XML В TEMP-TABLE И PRODATASET
Для импорта данных их XML файла в temp-table или ProDataSet используется метод READ-XML, возвращающий логическое значение, отражающее успешность (TRUE) или не успешность (FALSE) выполнения импорта:
READ-XML(source-type,
source,
read-mode,
schema-location,
override-default-mapping
[,field-type-mapping [,verify-schema-mode]].
source-type - значение CHAR типа, определяет тип источника XML и может принимать следующие значения:
- FILE - чтение из файла;
- MEMPTR - чтение из переменной MEMPTR типа;
- HANDLE - указатель источника;
- LONGCHAR - чтение из переменной или поля таблицы LONGCHAR типа;
source - определяет источник импортируемого XML. Так для source-type = FILE это путь к XML-файлу, для LONGCHAR - идентификатор переменной или поля таблицы.
read-mode - определяет метод импорта данных:
- APPEND - осуществляется добавление записей из XML к уже существующим в temp-table/ProDataSet. В случае если определен UNIQUIE индекс и при импорте данных окажутся дублирующие записи, возникнет ошибка импорта и результат метода при этом будет FALSE.
- EMPTY - осуществляется предварительная очистка temp-table/ProDataSet от уже имеющихся в них данных перед импортом из XML.
- MERGE - осуществляет слияние имеющихся данных в temp-table/ProDataSet и данных импортируемых из XML. В случае, если в таблице определен UNIQUIE индекс и при импорте данных могут возникнуть дублирующие записи, то имеющаяся запись в temp-table/ProDataSet не будет изменена.
- REPLACE - осуществляет замещение существующих в temp-table/ProDataSet записей, записями из XML, в случае, если определен UNIQUIE индекс и при импорте данных могут возникнуть дублирующие записи.
schema-location - определяет расположение файла XML-схемы используемой для валидации XML-документа. В случае если shema-location не определена (пустое значение или ?) AVM осуществит поиск схемы в следующей последовательности:
- дочерний элемент <schema> корня XML-документа;
- атрибут xsi:schemaLocation или xsi:noNamespaceSchemaLocation XML-документа.
override-default-mapping -
field-type-mapping -
verify-schema-mode - значение CHAR типа определяющее режим верификации, осуществляемой на основе XML-схемы, указанной в schema-location или в структуре XML. Может принимать следующие значения:
- IGNOR - верификация не осуществляется.
- LOOSE - осуществляет сверку элементов temp-table или ProDataSet с соответствующими им элементами XML-схемы. Данный режим допускает несовпадение структур temp-table/ProDataSet и XML-схемы. Элементы temp-table или ProDataSet, для которых отсутствуют соответствующие элементы в XML-схеме - игнорируются.
- STRICT - жесткий режим верификации, при котором структура temp-table или ProDataSet должна полностью соответствовать XML-схеме.
Мы будем осуществлять импорт данных во временную таблицу из заранее приготовленного XML-файла
lResult = TEMP-TABLE tt-Person:READ-XML("FILE",
"./PersonInfo.xml",
"EMPTY",
?,
?,
?,
?).
ЭКСПОРТ ДАННЫХ В XML ИЗ TEMP-TABLE И PRODATASET
Для экспорта данных временной таблицы или ProDataSet используется метод WRITE-XML:
WRITE-XML(target-type,
target
[, formatted
[, encoding
[, shema-location
[, write-xmlschema
[, min-xmlschema
[, write-before-image
[, omit-initial-values]]]]]]]).
target-type - определяет тип приемника данных, в который осуществляется экспорт XML. Может принимать следующие значения:
- FILE - запись в файл;
- STREAM - запись в поток;
- MEMPTR - запись в переменную MEMPTR типа;
- HANDLE - указатель приемника;
- LONGCHAR - запись в переменную или поле таблицы LONGCHAR типа;
target - определяет приемник, в который осуществляется запись XML. Так для source-type = FILE это путь к XML файлу, для LONGCHAR - идентификатор переменной.
lResult = TEMP-TABLE tt-persons:WRITE-XML("FILE",
"./PersonInfo.xml",
TRUE).
В результате, в рабочем каталоге пользователя будет сформирован файл PersonInfo.xml:
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersonRow>
<personName>Иванов Иван Иванович</personName>
<birthday>1979-10-26</birthday>
<personTown>Москва</personTown>
</PersonRow>
<PersonRow>
<personName>Николаев Николай Николаевич</personName>
<birthday>1965-08-22</birthday>
<personTown>Нижний Новгород</personTown>
</PersonRow>
<PersonRow>
<personName>Сергеев Сергей Сергеевич</personName>
<birthday>1981-04-11</birthday>
<personTown>Самара</personTown>
</PersonRow>
</Person>
DEF VAR oData AS LONGCHAR NO-UNDO.
lResult = TEMP-TABLE tt-persons:WRITE-XML("LONGCHAR",
"oData",
TRUE).
В данном примере, данные временной таблицы, представленные в формате XML, будут записаны в переменную oData.
formatted - логическое значение, определяющее представление данных в XML-файле. При значении TRUE данные будут представлены в структурированном виде с применением переноса строки и табуляции, а при FALSE или ?, данные будут представлены единой строкой.
lResult = TEMP-TABLE tt-persons:WRITE-XML("FILE",
"./PersonInfo.xml",
FALSE).
<?xml version="1.0"?><Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><PersonRow><personName>Иванов Иван Иванович</personName><birthday>1979-10-26</birthday><personTown>Москва</personTown></PersonRow><PersonRow><personName>Николаев Николай Николаевич</personName><birthday>1965-08-22</birthday><personTown>Нижний Новгород</personTown></PersonRow><PersonRow><personName>Сергеев Сергей Сергеевич</personName><birthday>1981-04-11</birthday><personTown>Самара</personTown></PersonRow></Person>
encoding - определяет кодировку XML. Данное значение записывается в атрибут encoding пролога XML.
lResult = TEMP-TABLE tt-persons:WRITE-XML("FILE",
"./PersonInfo.xml",
TRUE,
"windows-1251").
shema-location - определяет расположение файла XML-схемы, используемой для валидации XML-документа. Определяет значение атрибута xsi:schemaLocation или xsi:noNamespaceSchemaLocation, формируемого XML-документа.
lResult = TEMP-TABLE tt-persons:WRITE-XML("FILE",
"./PersonInfo.xml",
TRUE,
"windows-1251",
"./PersonInfo.xsd").
<?xml version="1.0" encoding="windows-1251"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./PersonInfo.xsd">
<PersonRow>
<personName>Иванов Иван Иванович</personName>
<birthday>1979-10-26</birthday>
<personTown>Москва</personTown>
</PersonRow>
<PersonRow>
<personName>Николаев Николай Николаевич</personName>
<birthday>1965-08-22</birthday>
<personTown>Нижний Новгород</personTown>
</PersonRow>
<PersonRow>
<personName>Сергеев Сергей Сергеевич</personName>
<birthday>1981-04-11</birthday>
<personTown>Самара</personTown>
</PersonRow>
</Person>
write-xmlschema - логическое значение, определяющее формирование XML-схемы совместно с данными, если значение равно TRUE. Значением по умолчанию является FALSE, при котором выгружаются только данные. Не может использоваться совместно с shema-location.
lResult = TEMP-TABLE tt-persons:WRITE-XML("FILE",
"./PersonInfo1.xml",
TRUE,
"windows-1251",
?,
TRUE).
<?xml version="1.0" encoding="windows-1251"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="" xmlns:prodata="urn:schemas-progress-com:xml-prodata:0001">
<xsd:element name="Person" prodata:proTempTable="true" prodata:tableName="tt-persons" prodata:undo="true">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="PersonRow" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="personName" type="xsd:string" nillable="true" prodata:fieldName="fio"/>
<xsd:element name="birthday" type="xsd:date" nillable="true" prodata:fieldName="birthday"/>
<xsd:element name="personTown" type="xsd:string" nillable="true" prodata:fieldName="town"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<PersonRow>
<personName>Иванов Иван Иванович</personName>
<birthday>1979-10-26</birthday>
<personTown>Москва</personTown>
</PersonRow>
<PersonRow>
<personName>Николаев Николай Николаевич</personName>
<birthday>1965-08-22</birthday>
<personTown>Нижний Новгород</personTown>
</PersonRow>
<PersonRow>
<personName>Сергеев Сергей Сергеевич</personName>
<birthday>1981-04-11</birthday>
<personTown>Самара</personTown>
</PersonRow>
</Person>
min-xmlschema - логическое значение, определяющее формат XML-схемы. При значение TRUE формат XML-схемы будет минимизированным, при FALSE - развернутым. Значением по умолчанию является FALSE.
write-before-image -
omit-initial-values - логическое значение, исключающее из выгрузки в XML полей таблицы содержащие их начальные значения. По умолчанию равно FALSE, т.е. в XML выгружаются все поля таблицы.
lResult = DATASET dataPersons:WRITE-XML("FILE",
"./dataPersons.xml",
FALSE,
"utf-8").
Содержимое XML файла сформированного на основе данных ProDateSet будет записано в файл dataPersons.xml.