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.

 

Вы здесь: Главная Основы ABL TEMP-TABLE, PRODATASET ИМПОРТ-ЭКСПОРТ ДАННЫХ XML