Тип таблицы CONNECT XML
Обзор
CONNECT поддерживает таблицы, представленные файлами XML. Для этих таблиц не используются стандартные функции ввода/вывода операционной системы, а парсинг и обработка файла делегируются специализированной библиотеке. В настоящее время поддерживаются две такие системы: libxml2, часть фреймворка GNOME, но не требующая GNOME, и, в Windows, MS-DOM (DOMDOC), стандартная поддержка XML-документов Microsoft.
DOMDOC является значением по умолчанию для Windows-версии CONNECT, а libxml2 всегда используется на других системах. В Windows выбор можно указать с помощью опции списка XMLSUP CREATE TABLE, например, указав option_list='xmlsup=libxml2'.
Создание XML-таблиц
Прежде всего, необходимо понимать, что XML — это очень универсальный язык, используемый для кодирования данных с любой структурой. В частности, иерархия тегов в XML-файле описывает древовидную структуру данных. Например, рассмотрим файл:
<?xml version="1.0" encoding="ISO-8859-1"?>
<BIBLIO SUBJECT="XML">
<BOOK ISBN="9782212090819" LANG="fr" SUBJECT="applications">
<AUTHOR>
<FIRSTNAME>Jean-Christophe</FIRSTNAME>
<LASTNAME>Bernadac</LASTNAME>
</AUTHOR>
<AUTHOR>
<FIRSTNAME>François</FIRSTNAME>
<LASTNAME>Knab</LASTNAME>
</AUTHOR>
<TITLE>Construire une application XML</TITLE>
<PUBLISHER>
<NAME>Eyrolles</NAME>
<PLACE>Paris</PLACE>
</PUBLISHER>
<DATEPUB>1999</DATEPUB>
</BOOK>
<BOOK ISBN="9782840825685" LANG="fr" SUBJECT="applications">
<AUTHOR>
<FIRSTNAME>William J.</FIRSTNAME>
<LASTNAME>Pardi</LASTNAME>
</AUTHOR>
<TRANSLATOR PREFIX="adapté de l'anglais par">
<FIRSTNAME>James</FIRSTNAME>
<LASTNAME>Guerin</LASTNAME>
</TRANSLATOR>
<TITLE>XML en Action</TITLE>
<PUBLISHER>
<NAME>Microsoft Press</NAME>
<PLACE>Paris</PLACE>
</PUBLISHER>
<DATEPUB>1999</DATEPUB>
</BOOK>
</BIBLIO>
Он представляет данные со структурой:
<BIBLIO>
__________|_________
| |
<BOOK:ISBN,LANG,SUBJECT> |
______________|_______________ |
| | | | |
<AUTHOR> <TITLE> <PUBLISHER> <DATEPUB> |
____|____ ___|____ |
| | | | | |
<FIRST> | <LAST> <NAME> <PLACE> |
| |
<AUTHOR> <BOOK:ISBN,LANG,SUBJECT>
____|____ ______________________|__________________
| | | | | | |
<FIRST> <LAST> <AUTHOR> <TRANSLATOR> <TITLE> <PUBLISHER> <DATEPUB>
_____|_ ___|___ ___|____
| | | | | |
<FIRST> <LAST> <FIRST> <LAST> <NAME> <PLACE>
На первый взгляд эта структура далека от табличной. Однако современные системы управления базами данных, включая MariaDB, реализуют нечто близкое к реляционной модели и работают с таблицами, которые по структуре не иерархичны, а табличные с строками и столбцами.
Тем не менее, CONNECT может это сделать. Конечно, он не может угадать, что вы хотите извлечь из структуры XML, но предоставляет возможность указать это при создании таблицы[1].
Давайте рассмотрим первый пример. Предположим, вы хотите создать таблицу из приведенного выше документа, отображая содержимое узла.
Для этого вы можете определить таблицу xsamptag как:
create table xsamptag ( AUTHOR char(50), TITLE char(32), TRANSLATOR char(40), PUBLISHER char(40), DATEPUB int(4)) engine=CONNECT table_type=XML file_name='Xsample.xml';
Она будет отображена как:
| АВТОР | НАЗВАНИЕ | ПЕРЕВОДЧИК | ИЗДАТЕЛЬ | ДАТА_ИЗДАНИЯ |
|---|---|---|---|---|
| Jean-Christophe Bernadac | Construire une application XML | <null> | Eyrolles Paris | 1999 |
| William J. Pardi | XML en Action | James Guerin | Microsoft Press Paris | 1999 |
Давайте попытаемся понять, что произошло. По умолчанию имена столбцов соответствуют именам тегов. Поскольку этот файл достаточно простой, CONNECT смог установить тег верхнего уровня таблицы в качестве корневого узла <BIBLIO> файла, а теги строк — как <BOOK> дочерние узлы тега таблицы. В более сложном файле это следовало бы указать, как мы увидим позже. Обратите внимание, что нам не нужно было беспокоиться о подтегах, таких как <FIRSTNAME> или <LASTNAME>, поскольку CONNECT автоматически извлекает все содержимое тега и его подтегов[2].
Показывается только первый автор первой книги. Это происходит потому, что извлечена только первая встреча тега столбца, поэтому результат имеет правильную табличную структуру. Мы увидим позже, что можно сделать по этому поводу.
Как мы можем извлечь значения, заданные атрибутами? Используя опцию таблицы Coltype для указания типа столбца по умолчанию. Значение ‘@’ означает, что имена столбцов соответствуют именам атрибутов. Следовательно, мы можем извлечь их, создав таблицу, такую как:
create table xsampattr ( ISBN char(15), LANG char(2), SUBJECT char(32)) engine=CONNECT table_type=XML file_name='Xsample.xml' option_list='Coltype=@';
Эта таблица возвращает следующее:
| ISBN | ЯЗ | ТЕМА |
|---|---|---|
| 9782212090819 | fr | приложения |
| 9782840825685 | fr | приложения |
Теперь, чтобы определить таблицу, которая предоставит нам всю предыдущую информацию, мы должны указать тип столбца для каждого столбца. Поскольку в следующем операторе тип столбца по умолчанию равен Node, параметр столбца field_format использовался для указания столбцов, которые являются атрибутами:
С Connect 1.7.0002
create table xsamp ( ISBN char(15) xpath='@', LANG char(2) xpath='@', SUBJECT char(32) xpath='@', AUTHOR char(50), TITLE char(32), TRANSLATOR char(40), PUBLISHER char(40), DATEPUB int(4)) engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK';
До Connect 1.7.0002
create table xsamp ( ISBN char(15) field_format='@', LANG char(2) field_format='@', SUBJECT char(32) field_format='@', AUTHOR char(50), TITLE char(32), TRANSLATOR char(40), PUBLISHER char(40), DATEPUB int(4)) engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK';
После выполнения можно ввести запрос:
select subject, lang, title, author from xsamp;
Это вернет следующий результат:
| ТЕМА | ЯЗ | НАЗВАНИЕ | АВТОР |
|---|---|---|---|
| приложения | fr | Construire une application XML | Jean-Christophe Bernadac |
| приложения | fr | XML en Action | William J. Pardi |
Обратите внимание, что нам повезло. Поскольку в отличие от SQL, XML чувствителен к регистру, имена столбцов совпали с именами узлов только потому, что имена столбцов были указаны в верхнем регистре. Обратите также внимание, что порядок столбцов в таблице мог отличаться от порядка появления узлов в XML-файле.
Использование Xpath с XML-таблицами
Xpath используется в XML для поиска и извлечения узлов. Основной Xpath-узел таблицы задается опцией tabname. Если указано только имя узла, CONNECT строит Xpath, например, ‘BIBLIO’ в приведенном выше примере, который должен извлечь узел BIBLIO где угодно в XML-файле.
Узлы строк по умолчанию являются дочерними узлами узла таблицы. Однако, например, для исключения некоторых дочерних узлов, которые не являются реальными узлами строк, имя узла строки можно указать с помощью подопции rownode опции option_list.
Используемые выше опции field_format можно указать, чтобы более точно определить, где и какую информацию извлечь, используя синтаксис, похожий на Xpath. Например:
С Connect 1.7.0002
create table xsampall ( isbn char(15) xpath='@ISBN', language char(2) xpath='@LANG', subject char(32) xpath='@SUBJECT', authorfn char(20) xpath='AUTHOR/FIRSTNAME', authorln char(20) xpath='AUTHOR/LASTNAME', title char(32) xpath='TITLE', translated char(32) xpath='TRANSLATOR/@PREFIX', tranfn char(20) xpath='TRANSLATOR/FIRSTNAME', tranln char(20) xpath='TRANSLATOR/LASTNAME', publisher char(20) xpath='PUBLISHER/NAME', location char(20) xpath='PUBLISHER/PLACE', year int(4) xpath='DATEPUB') engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK';
До Connect 1.7.0002
create table xsampall ( isbn char(15) field_format='@ISBN', language char(2) field_format='@LANG', subject char(32) field_format='@SUBJECT', authorfn char(20) field_format='AUTHOR/FIRSTNAME', authorln char(20) field_format='AUTHOR/LASTNAME', title char(32) field_format='TITLE', translated char(32) field_format='TRANSLATOR/@PREFIX', tranfn char(20) field_format='TRANSLATOR/FIRSTNAME', tranln char(20) field_format='TRANSLATOR/LASTNAME', publisher char(20) field_format='PUBLISHER/NAME', location char(20) field_format='PUBLISHER/PLACE', year int(4) field_format='DATEPUB') engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK';
Этот очень гибкий параметр столбца служит нескольким целям:
- Указать имя тега или имя атрибута, если оно отличается от имени столбца.
- Указать тип (тег или атрибут) с префиксом ‘@’ для атрибутов.
- Указать путь к подтегам с использованием символа «/».
Этот путь всегда является относительным по отношению к текущему контексту (узлу верхнего уровня столбца) и не может быть указан как абсолютный путь от корня документа, поэтому ведущий символ «/» использовать нельзя. Путь не может быть переменным по именам узлов или глубине, поэтому использование '//' запрещено.
Запрос:
select isbn, title, translated, tranfn, tranln, location from
xsampall where translated is not null;
отвечает:
| ISBN | НАЗВАНИЕ | ПЕРЕВЕДЕН | TRANFN | TRANLN | МЕСТОПОЛОЖЕНИЕ |
|---|---|---|---|---|---|
| 9782840825685 | XML en Action | adapté de l'anglais par | James | Guerin | Paris |
Проблема с пространством имен по умолчанию libxml2
Проблема с libxml2 заключается в том, что некоторые файлы могут объявлять пространство имен по умолчанию в своем корневом узле. Поскольку Xpath ищет только в этом пространстве имен, узлы не будут найдены, если они не имеют префикса. Если это происходит, укажите опцию tabname как Xpath, игнорируя текущее пространство имен:
TABNAME="//*[local-name()='BIBLIO']"
Это также необходимо сделать для значения по умолчанию указанного Xpath атрибутивных столбцов. Например:
title char(32) field_format="*[local-name()='TITLE']",
Примечание: это вызывает ошибку (и, в любом случае, бесполезно) с DOMDOC.
Прямой доступ к XML-таблицам
Прямой доступ доступен для XML-таблиц. Это означает, что XML-таблицы можно сортировать и использовать в объединениях, даже в одностороннем объединении.
Однако создание постоянного индекса пока не реализовано. Неясно, будет ли это полезно. Действительно, реализация DOM, используемая для доступа к этим таблицам, сначала анализирует весь файл и строит древо узлов в памяти. Это часто может быть самой длительной частью процесса, поэтому использование индекса не будет иметь большого значения. Обратите также внимание, что это ограничивает XML-файлы разумным размером. В любом случае, когда скорость важна, этот тип таблицы не лучший вариант. Поэтому в этих случаях, вероятно, лучше преобразовать файл в другой тип, вставив XML-таблицу в другую таблицу более подходящего типа для повышения производительности.
Доступ к тегам с именованными пространствами
С поддержкой Windows DOMDOC это можно сделать, используя префикс в опции столбца tabname и/или xpath столбца. Например, учитывая файл gns.xml:
<?xml version="1.0" encoding="UTF-8"?> <gpx xmlns:gns="http:dummy"> <gns:trkseg> <trkpt lon="-121.9822235107421875" lat="37.3884925842285156"> <gns:ele>6.610851287841797</gns:ele> <time>2014-04-01T14:54:05.000Z</time> </trkpt> <trkpt lon="-121.9821929931640625" lat="37.3885803222656250"> <ele>6.787827968597412</ele> <time>2014-04-01T14:54:08.000Z</time> </trkpt> <trkpt lon="-121.9821624755859375" lat="37.3886299133300781"> <ele>6.771987438201904</ele> <time>2014-04-01T14:54:10.000Z</time> </trkpt> </gns:trkseg> </gpx>
и определенную таблицу CONNECT:
CREATE TABLE xgns ( `lon` double(21,16) NOT NULL `xpath`='@', `lat` double(20,16) NOT NULL `xpath`='@', `ele` double(21,16) NOT NULL `xpath`='gns:ele', `time` datetime date_format="YYYY-MM-DD 'T' hh:mm:ss '.000Z'" ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=XML `file_name`='gns.xml' tabname='gns:trkseg' option_list='xmlsup=domdoc';
select * from xgns;
Отображается:
| lon | lat | ele | time |
|---|---|---|---|
| -121,982223510742 | 37,3884925842285 | 6,6108512878418 | 01/04/2014 14:54:05 |
| -121,982192993164 | 37,3885803222656 | 0 | 01/04/2014 14:54:08 |
| -121,982162475586 | 37,3886299133301 | 0 | 01/04/2014 14:54:10 |
Распознается только тег ‘ele’ с префиксом.
Однако это не работает с поддержкой libxml2. Решение — использовать функцию, игнорирующую пространство имен:
CREATE TABLE xgns2 ( `lon` double(21,16) NOT NULL `xpath`='@', `lat` double(20,16) NOT NULL `xpath`='@', `ele` double(21,16) NOT NULL `xpath`="*[local-name()='ele']", `time` datetime date_format="YYYY-MM-DD 'T' hh:mm:ss '.000Z'" ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `table_type`=XML `file_name`='gns.xml' tabname="*[local-name()='trkseg']" option_list='xmlsup=libxml2';
Затем:
select * from xgns2;
Отображается:
| lon | lat | ele | time |
|---|---|---|---|
| -121,982223510742 | 37,3884925842285 | 6,6108512878418 | 01/04/2014 14:54:05 |
| -121,982192993164 | 37,3885803222656 | 6.7878279685974 | 01/04/2014 14:54:08 |
| -121,982162475586 | 37,3886299133301 | 6.7719874382019 | 01/04/2014 14:54:10 |
На этот раз распознаются все теги ‘ele`. Это решение не работает с DOMDOC.
Определение столбцов путем обнаружения
Можно позволить процессу обнаружения MariaDB выполнить задачу задания спецификаций столбцов. Когда столбцы не определены в операторе CREATE TABLE, CONNECT пытается проанализировать XML-файл и предоставить спецификации столбцов. Это возможно только для истинных XML-таблиц, но не для HTML-таблиц.
Например, таблицу xsamp можно было создать, указав:
create table xsamp engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK';
Давайте проверим, как она была фактически указана с помощью оператора SHOW CREATE TABLE:
CREATE TABLE `xsamp` ( `ISBN` char(13) NOT NULL `FIELD_FORMAT`='@', `LANG` char(2) NOT NULL `FIELD_FORMAT`='@', `SUBJECT` char(12) NOT NULL `FIELD_FORMAT`='@', `AUTHOR` char(24) NOT NULL, `TRANSLATOR` char(12) DEFAULT NULL, `TITLE` char(30) NOT NULL, `PUBLISHER` char(21) NOT NULL, `DATEPUB` char(4) NOT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='XML' `FILE_NAME`='E:/Data/Xml/Xsample.xml' `TABNAME`='BIBLIO' `OPTION_LIST`='rownode=BOOK';
Это эквивалентно, за исключением размеров столбцов, которые были рассчитаны из файла как максимальная длина соответствующего столбца, когда он был обычным значением. Кроме того, все столбцы указаны как тип CHAR, потому что XML не предоставляет информацию о типе данных содержимого узла. Значение NULL установлено в TRUE, если столбец отсутствует в некоторых строках.
Если требуется более сложное определение, вы можете попросить CONNECT проанализировать XPATH до заданного уровня, используя опцию level в списке опций. Значение level — это количество узлов, которые используются в XPATH. Например:
create table xsampall engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK,Level=1';
Это определит таблицу как:
С Connect 1.7.0002
CREATE TABLE `xsampall` (
`ISBN` char(13) NOT NULL `XPATH`='@',
`LANG` char(2) NOT NULL `XPATH`='@',
`SUBJECT` char(12) NOT NULL `XPATH`='@',
`AUTHOR_FIRSTNAME` char(15) NOT NULL `XPATH`='AUTHOR/FIRSTNAME',
`AUTHOR_LASTNAME` char(8) NOT NULL `XPATH`='AUTHOR/LASTNAME',
`TRANSLATOR_PREFIX` char(24) DEFAULT NULL `XPATH`='TRANSLATOR/@PREFIX',
`TRANSLATOR_FIRSTNAME` char(7) DEFAULT NULL `XPATH`='TRANSLATOR/FIRSTNAME',
`TRANSLATOR_LASTNAME` char(6) DEFAULT NULL `XPATH`='TRANSLATOR/LASTNAME',
`TITLE` char(30) NOT NULL,
`PUBLISHER_NAME` char(15) NOT NULL `XPATH`='PUBLISHER/NAME',
`PUBLISHER_PLACE` char(5) NOT NULL `XPATH`='PUBLISHER/PLACE',
`DATEPUB` char(4) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='XML' `FILE_NAME`='Xsample.xml' `TABNAME`='BIBLIO' `OPTION_LIST`='rownode=BOOK,Depth=1';
<</sql>>
Before Connect 1.7.0002
<<sql>>
CREATE TABLE `xsampall` (
`ISBN` char(13) NOT NULL `FIELD_FORMAT`='@',
`LANG` char(2) NOT NULL `FIELD_FORMAT`='@',
`SUBJECT` char(12) NOT NULL `FIELD_FORMAT`='@',
`AUTHOR_FIRSTNAME` char(15) NOT NULL `FIELD_FORMAT`='AUTHOR/FIRSTNAME',
`AUTHOR_LASTNAME` char(8) NOT NULL `FIELD_FORMAT`='AUTHOR/LASTNAME',
`TRANSLATOR_PREFIX` char(24) DEFAULT NULL `FIELD_FORMAT`='TRANSLATOR/@PREFIX',
`TRANSLATOR_FIRSTNAME` char(7) DEFAULT NULL `FIELD_FORMAT`='TRANSLATOR/FIRSTNAME',
`TRANSLATOR_LASTNAME` char(6) DEFAULT NULL `FIELD_FORMAT`='TRANSLATOR/LASTNAME',
`TITLE` char(30) NOT NULL,
`PUBLISHER_NAME` char(15) NOT NULL `FIELD_FORMAT`='PUBLISHER/NAME',
`PUBLISHER_PLACE` char(5) NOT NULL `FIELD_FORMAT`='PUBLISHER/PLACE',
`DATEPUB` char(4) NOT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='XML' `FILE_NAME`='Xsample.xml'
`TABNAME`='BIBLIO' `OPTION_LIST`='rownode=BOOK,Level=1';
<</sql>>
This method can be used as a quick way to make a “template” table definition that can later be edited to make the desired definition. In particular, column names are constructed from all the nodes of their path in order to have distinct column names. This can be manually edited to have the desired names, provided their XPATH is not modified.
To have a preview of how columns will be defined, you can use a catalog table like this:
<<sql>>
create table xsacol
engine=CONNECT table_type=XML file_name='Xsample.xml'
tabname='BIBLIO' option_list='rownode=BOOK,Level=1' catfunc=col;
<</sql>>
And when asking:
<<sql>>
select column_name Name, type_name Type, column_size Size, nullable, xpath from xsacol;
<</sql>>
You get the description of what the table columns will be:
<<style class="darkheader-nospace-borders">>
|= Name |= Type |= Size |= nullable |= xpath |
| ISBN | CHAR | 13 | 0 | @ |
| LANG | CHAR | 2 | 0 | @ |
| SUBJECT | CHAR | 12 | 0 | @ |
| AUTHOR_FIRSTNAME | CHAR | 15 | 0 | AUTHOR/FIRSTNAME |
| AUTHOR_LASTNAME | CHAR | 8 | 0 | AUTHOR/LASTNAME |
| TRANSLATOR_PREFIX | CHAR | 24 | 1 | TRANSLATOR/@PREFIX |
| TRANSLATOR_FIRSTNAME | CHAR | 7 | 1 | TRANSLATOR/FIRSTNAME |
| TRANSLATOR_LASTNAME | CHAR | 6 | 1 | TRANSLATOR/LASTNAME |
| TITLE | CHAR | 30 | 0 | |
| PUBLISHER_NAME | CHAR | 15 | 0 | PUBLISHER/NAME |
| PUBLISHER_PLACE | CHAR | 5 | 0 | PUBLISHER/PLACE |
| DATEPUB | CHAR | 4 | 0 | |
<</style>>
== Write operations on XML tables
You can freely use the Update, Delete and Insert commands with XML tables.
However, you must understand that the format of the updated or inserted data
follows the specifications of the table you created, not the ones of the
original source file. For instance, let us suppose we insert a new book using
the //xsamp// table (not the //xsampall// table) with the command:
<<code lang=mysql inline=false>>
insert into xsamp
(isbn, lang, subject, author, title, publisher,datepub)
values ('9782212090529','fr','général','Alain Michard',
'XML, Langage et Applications','Eyrolles Paris',1998);
Затем, если мы запросим:
select subject, author, title, translator, publisher from xsamp;
Все кажется правильным, когда мы получаем результат:
| ПРЕДМЕТ | АВТОР | НАЗВАНИЕ | ПЕРЕВОДЧИК | ИЗДАТЕЛЬ |
|---|---|---|---|---|
| приложения | Жан-Кристоф Бернадак | Создание XML-приложения | Eyrolles Париж | |
| приложения | Уильям Дж. Парди | XML в действии | Джеймс Герен | Microsoft Press Париж |
| общее | Ален Мишар | XML, язык и приложения | Eyrolles Париж |
Однако, если мы введём, по-видимому, эквивалентный запрос к таблице xsampall, основанной на том же файле:
select subject, concat(authorfn, ' ', authorln) author , title, concat(tranfn, ' ', tranln) translator, concat(publisher, ' ', location) publisher from xsampall;
это вернёт, по-видимому, неправильный ответ:
| ПРЕДМЕТ | АВТОР | НАЗВАНИЕ | ПЕРЕВОДЧИК | ИЗДАТЕЛЬ |
|---|---|---|---|---|
| приложения | Жан-Кристоф Бернадак | Создание XML-приложения | Eyrolles Париж | |
| приложения | Уильям Дж. Парди | XML в действии | Джеймс Герен | Microsoft Press Париж |
| общее | XML, язык и приложения |
Что здесь произошло? Просто потому, что мы использовали таблицу xsamp для выполнения операции Вставка, то, что было вставлено в XML-файл, имело структуру, описанную для xsamp:
<BOOK ISBN="9782212090529" LANG="fr" SUBJECT="général">
<AUTHOR>Alain Michard</AUTHOR>
<TITLE>XML, Langage et Applications</TITLE>
<TRANSLATOR></TRANSLATOR>
<PUBLISHER>Eyrolles Paris</PUBLISHER>
<DATEPUB>1998</DATEPUB>
</BOOK>
CONNECT не может «выдумать» подтеги, которые не являются частью таблицы xsamp. Поскольку эти подтеги не существуют, таблица xsampall не может извлечь информацию, которая должна быть к ним прикреплена. Если мы хотим иметь возможность запросить XML-файл по всем определённым таблицам, правильный способ вставки новой книги в файл — использовать таблицу xsampall, единственную, которая охватывает все компоненты исходного документа:
delete from xsamp where isbn = '9782212090529';
insert into xsampall (isbn, language, subject, authorfn, authorln,
title, publisher, location, year)
values('9782212090529','fr','général','Alain','Michard',
'XML, Langage et Applications','Eyrolles','Paris',1998);
Теперь добавленная книга в XML-файле будет иметь необходимую структуру:
<BOOK ISBN="9782212090529" LANG="fr" SUBJECT="général">
<AUTHOR>
<FIRSTNAME>Alain</FIRSTNAME>
<LASTNAME>Michard</LASTNAME>
</AUTHOR>
<TITLE>XML, Langage et Applications</TITLE>
<PUBLISHER>
<NAME>Eyrolles</NAME>
<PLACE>Paris</PLACE>
</PUBLISHER>
<DATEPUB>1998</DATEPUB>
</BOOK>
Примечание: Мы использовали список столбцов в операциях Вставки при создании таблицы, чтобы избежать создания узла <TRANSLATOR> с подузлами, все содержащие нулевые значения (это работает только в Windows).
Множественные узлы в XML-документе
Давайте вернёмся к вышеприведённому примеру XML-файла. Мы видели, что узел автора может быть «множественным», то есть может быть более одного автора книги. Что мы можем сделать, чтобы получить полную информацию, соответствующую реляционной модели? CONNECT предоставляет вам две возможности, но ограничен только одним таким множественным узлом на таблицу.
Первая и самая сложная — вернуть столько строк, сколько авторов, при этом другие столбцы повторяются так, как будто мы выполнили объединение между столбцом автора и остальными таблицами. Для этого просто укажите имя узла «множественный» и параметр «расширить» при создании таблицы. Например, мы можем создать таблицу xsamp2 следующим образом:
create table xsamp2 ( ISBN char(15) field_format='@', LANG char(2) field_format='@', SUBJECT char(32) field_format='@', AUTHOR char(40), TITLE char(32), TRANSLATOR char(32), PUBLISHER char(32), DATEPUB int(4)) engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK,Expand=1,Mulnode=AUTHOR,Limit=2';
В этом операторе параметр Limit задаёт максимальное количество значений, которые будут расширены. Если он не указан, он по умолчанию равен 10. Любые значения, превышающие лимит, будут проигнорированы, и будет выведено сообщение об ошибке[3]. Теперь вы можете ввести такой запрос:
select isbn, subject, author, title from xsamp2;
Это вернёт и отобразит следующий результат:
| ISBN | ПРЕДМЕТ | АВТОР | НАЗВАНИЕ |
|---|---|---|---|
| 9782212090819 | приложения | Жан-Кристоф Бернадак | Создание XML-приложения |
| 9782212090819 | приложения | Франсуа Кнаб | Создание XML-приложения |
| 9782840825685 | приложения | Уильям Дж. Парди | XML в действии |
| 9782212090529 | общее | Ален Мишар | XML, язык и приложения |
В этом случае это, как если бы таблица имела четыре строки. Однако, если мы введём запрос:
select isbn, subject, title, publisher from xsamp2;
на этот раз результатом будет:
| ISBN | ПРЕДМЕТ | НАЗВАНИЕ | ИЗДАТЕЛЬ |
|---|---|---|---|
| 9782212090819 | приложения | Создание XML-приложения | Eyrolles Париж |
| 9782840825685 | приложения | XML в действии | Microsoft Press Париж |
| 9782212090529 | общее | XML, язык и приложения | Eyrolles Париж |
Поскольку столбец автор не появляется в запросе, соответствующая строка не была расширена. Это несколько странно, потому что это было бы иначе, если бы мы работали с таблицей другого типа. Однако это ближе к реляционной модели, для которой в таблице не должно быть двух одинаковых строк (кортежей). Тем не менее, вы должны быть осведомлены об этом несколько непредсказуемом поведении. Например:
select count(*) from xsamp2; /* Replies 3 */ select count(author) from xsamp2; /* Replies 4 */ select count(isbn) from xsamp2; /* Replies 3 */ select isbn, subject, title, publisher from xsamp2 where author <> '';
Этот последний запрос возвращает:
| ISBN | ПРЕДМЕТ | НАЗВАНИЕ | ИЗДАТЕЛЬ |
|---|---|---|---|
| 9782212090819 | приложения | Создание XML-приложения | Eyrolles Париж |
| 9782212090819 | приложения | Создание XML-приложения | Eyrolles Париж |
| 9782840825685 | приложения | XML в действии | Microsoft Press Париж |
| 9782212090529 | общее | XML, язык и приложения | Eyrolles Париж |
Несмотря на то, что столбец автор не появляется в результате, соответствующая строка была расширена, потому что столбец множественный использовался в условии where.
Промежуточный множественный узел
Узел «множественный» может быть промежуточным узлом. Если мы хотим выполнить такое же расширение с таблицей xsampall, ничего больше делать не придётся. Таблица xsampall2 может быть создана с помощью:
С версии Connect 1.7.0002
create table xsampall2 ( isbn char(15) xpath='@ISBN', language char(2) xpath='@LANG', subject char(32) xpath='@SUBJECT', authorfn char(20) xpath='AUTHOR/FIRSTNAME', authorln char(20) xpath='AUTHOR/LASTNAME', title char(32) xpath='TITLE', translated char(32) xpath='TRANSLATOR/@PREFIX', tranfn char(20) xpath='TRANSLATOR/FIRSTNAME', tranln char(20) xpath='TRANSLATOR/LASTNAME', publisher char(20) xpath='PUBLISHER/NAME', location char(20) xpath='PUBLISHER/PLACE', year int(4) xpath='DATEPUB') engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK,Expand=1,Mulnode=AUTHOR,Limit=2';
До версии Connect 1.7.0002
create table xsampall2 ( isbn char(15) field_format='@ISBN', language char(2) field_format='@LANG', subject char(32) field_format='@SUBJECT', authorfn char(20) field_format='AUTHOR/FIRSTNAME', authorln char(20) field_format='AUTHOR/LASTNAME', title char(32) field_format='TITLE', translated char(32) field_format='TRANSLATOR/@PREFIX', tranfn char(20) field_format='TRANSLATOR/FIRSTNAME', tranln char(20) field_format='TRANSLATOR/LASTNAME', publisher char(20) field_format='PUBLISHER/NAME', location char(20) field_format='PUBLISHER/PLACE', year int(4) field_format='DATEPUB') engine=CONNECT table_type=XML file_name='Xsample.xml' tabname='BIBLIO' option_list='rownode=BOOK,Expand=1,Mulnode=AUTHOR,Limit=2';
Единственное различие заключается в том, что узел «множественный» является промежуточным узлом в пути. Результирующую таблицу можно увидеть с помощью запроса, например:
select subject, language lang, title, authorfn first, authorln
last, year from xsampall2;
Этот запрос отображает:
| ПРЕДМЕТ | ЯЗ | НАЗВАНИЕ | ИМЯ | ФАМИЛИЯ | ГОД |
|---|---|---|---|---|---|
| приложения | fr | Создание XML-приложения | Жан-Кристоф | Бернадак | 1999 |
| приложения | fr | Создание XML-приложения | Франсуа | Кнаб | 1999 |
| приложения | fr | XML в действии | Уильям Дж. | Парди | 1999 |
| общее | fr | XML, язык и приложения | Ален | Мишар | 1998 |
Эти составные таблицы, наполовину массив, наполовину дерево, содержат для нас некоторые сюрпризы при обновлении, удалении или вставке в них. Вставка просто не может сгенерировать эту структуру; если вставляются две строки только с разным автором, в XML-файле будут сгенерированы два узла книги. Удаление всегда удаляет один узел книги и все его дочерние узлы, даже если задано только по одному автору. Обновление сложнее:
update xsampall2 set authorfn = 'Simon' where authorln = 'Knab'; update xsampall2 set year = 2002 where authorln = 'Bernadac'; update xsampall2 set authorln = 'Mercier' where year = 2002;
После этих трёх обновлений, первые два возвращают «Затронутые строки: 1», а последний — «Затронутые строки: 2», последний запрос возвращает:
| предмет | язык | название | имя | фамилия | год |
|---|---|---|---|---|---|
| приложения | fr | Создание XML-приложения | Жан-Кристоф | Мерсье | 2002 |
| приложения | fr | Создание XML-приложения | Франсуа | Кнаб | 2002 |
| приложения | fr | XML в действии | Уильям Дж. | Парди | 1999 |
| общее | fr | XML, язык и приложения | Ален | Мишар | 1998 |
Здесь необходимо понимать, что обновление изменяет значения узлов в XML-файле, а не значения ячеек в реляционной таблице. Первое обновление работало нормально. Второе обновление изменило значение года книги, и это отображается для двух расширенных строк, поскольку для этой книги существует только один узел DATEPUB. Поскольку третье обновление применяется к строке, имеющей определённое значение даты, оба имени авторов были обновлены.
Создание списка множественных значений
Другой способ увидеть множественные значения — попросить CONNECT создать список значений множественного узла, разделённых запятыми. На этот раз это можно сделать только в том случае, если узел «множественный» не является промежуточным. Например, мы можем изменить определение таблицы xsamp2 следующим образом:
alter table xsamp2 option_list='rownode=BOOK,Mulnode=AUTHOR,Limit=3';
На этот раз 'Expand' не указан, а Limit определяет максимальное количество элементов в списке. Теперь, если мы введём запрос:
select isbn, subject, author "AUTHOR(S)", title from xsamp2;
Мы получим следующий результат:
| ISBN | ПРЕДМЕТ | АВТОР(Ы) | НАЗВАНИЕ |
|---|---|---|---|
| 9782212090819 | приложения | Жан-Кристоф Бернадак, Франсуа Кнаб | Создание XML-приложения |
| 9782840825685 | приложения | Уильям Дж. Парди | XML в действии |
| 9782212090529 | общее | Ален Мишар | XML, язык и приложения |
Обратите внимание, что обновление столбца «множественный» невозможно, так как CONNECT не знает, какой из узлов нужно обновить.
Это нельзя было сделать с таблицей xsampall2, потому что узел «автор» является промежуточным в пути, и составление двух списков, одного для имён и другого для фамилий, не имело бы смысла.
Что делать, если таблица содержит несколько множественных узлов
Это можно решить, создав несколько таблиц в одном файле, каждая из которых содержит только один множественный узел, и вычислив желаемый результат с помощью объединений.
Поддержка HTML-таблиц
Большинство таблиц, включённых в HTML-документы, не могут обрабатываться CONNECT, потому что язык HTML часто несовместим с синтаксисом XML. В частности, XML требует соответствия всех открытых тегов закрывающим тегам, в то время как в HTML это иногда необязательно. Это часто относится к тегам столбцов.
Однако вы можете встретить таблицы, которые соблюдают синтаксис XML, но имеют некоторые функции HTML-таблиц. Например:
<?xml version="1.0"?>
<Beers>
<table>
<th><td>Name</td><td>Origin</td><td>Description</td></th>
<tr>
<td><brandName>Huntsman</brandName></td>
<td><origin>Bath, UK</origin></td>
<td><details>Wonderful hop, light alcohol</details></td>
</tr>
<tr>
<td><brandName>Tuborg</brandName></td>
<td><origin>Danmark</origin></td>
<td><details>In small bottles</details></td>
</tr>
</table>
</Beers>
Здесь различные теги столбцов включаются в теги <td></td> как в HTML-таблицах. Вы не можете просто добавить этот тег в Xpath столбцов, потому что поиск выполняется на первом вхождении каждого тега, и это заставит этот поиск потерпеть неудачу для всех столбцов, кроме первого. Этот случай обрабатывается путём указания параметра таблицы Colnode, содержащего имя этих тегов столбцов, например:
С версии Connect 1.7.0002
create table beers ( `Name` char(16) xpath='brandName', `Origin` char(16) xpath='origin', `Description` char(32) xpath='details') engine=CONNECT table_type=XML file_name='beers.xml' tabname='table' option_list='rownode=tr,colnode=td';
До версии Connect 1.7.0002
create table beers ( `Name` char(16) field_format='brandName', `Origin` char(16) field_format='origin', `Description` char(32) field_format='details') engine=CONNECT table_type=XML file_name='beers.xml' tabname='table' option_list='rownode=tr,colnode=td';
Таблица будет отображаться следующим образом:
| Имя | Происхождение | Описание |
|---|---|---|
| Huntsman | Бат, Великобритания | Прекрасный хмель, низкое содержание алкоголя |
| Tuborg | Дания | В маленьких бутылках |
Однако вы можете работать с таблицами, ещё более близкими к HTML-модели. Например, файл coffee.htm:
<TABLE summary="This table charts the number of cups of coffe
consumed by each senator, the type of coffee (decaf
or regular), and whether taken with sugar.">
<CAPTION>Cups of coffee consumed by each senator</CAPTION>
<TR>
<TH>Name</TH>
<TH>Cups</TH>
<TH>Type of Coffee</TH>
<TH>Sugar?</TH>
</TR>
<TR>
<TD>T. Sexton</TD>
<TD>10</TD>
<TD>Espresso</TD>
<TD>No</TD>
</TR>
<TR>
<TD>J. Dinnen</TD>
<TD>5</TD>
<TD>Decaf</TD>
<TD>Yes</TD>
</TR>
</TABLE>
Здесь значения столбцов напрямую представлены текстом тега TD. Вы не можете объявлять их как теги или атрибуты. Кроме того, они не находятся по имени, а по положению в строке. Вот как объявить такую таблицу для CONNECT:
create table coffee ( `Name` char(16), `Cups` int(8), `Type` char(16), `Sugar` char(4)) engine=connect table_type=XML file_name='coffee.htm' tabname='TABLE' header=1 option_list='Coltype=HTML';
Вы указываете, что столбцы расположены по позиции, установив параметр Coltype в значение 'HTML'. Каждое положение столбца (нумерация с 0) будет значением параметра столбца flag, который устанавливается по умолчанию последовательно. Теперь мы можем отобразить таблицу:
| Имя | Чашки | Тип | Сахар |
|---|---|---|---|
| T. Sexton | 10 | Эспрессо | Нет |
| J. Dinnen | 5 | Декафеинированный | Да |
Примечание 1: Мы указали 'header=n' в операторе создания, чтобы указать, что первые n строк таблицы не являются строками данных и должны быть пропущены.
Примечание 2: В этом последнем примере мы не указали имена узлов, используя параметры Rownode и Colnode, потому что при установке Coltype в 'HTML' они по умолчанию устанавливаются в 'Rownode=TR' и 'Colnode=TD'.
Примечание 3: Параметр Coltype — это слово, только первая буква которого имеет значение. Распознаваемые значения:
| T(ag) или N(ode) | Имена столбцов соответствуют имени тега (по умолчанию). |
| A(ttribute) или @ | Имена столбцов соответствуют имени атрибута. |
| H(tml) или C(ol) или P(os) | Столбцы извлекаются по их позиции. |
Настройка нового файла
Некоторые параметры создания используются только при создании таблицы в новом файле, то есть при вставке в файл, которого ещё нет. При указании параметра 'Header' будет создана заголовочная строка с именем столбцов таблицы. Это особенно полезно для HTML-таблиц, которые должны отображаться в веб-браузере.
Некоторые новые параметры списка используются в этом контексте:
| Кодировка | Кодировка нового документа, по умолчанию UTF-8. |
| Атрибут | Список 'имя_атрибута=значение_атрибута', разделённых ';', для добавления в узел таблицы. |
| HeadAttr | Список атрибутов для добавления в узел строки заголовка. |
Давайте рассмотрим, например, следующий оператор создания:
create table handlers ( handler char(64), version char(20), author char(64), description char(255), maturity char(12)) engine=CONNECT table_type=XML file_name='handlers.htm' tabname='TABLE' header=yes option_list='coltype=HTML,encoding=ISO-8859-1, attribute=border=1;cellpadding=5,headattr=bgcolor=yellow';
Предполагая, что файл таблицы ещё не существует, первая вставка в эту таблицу, например, следующим оператором:
insert into handlers select plugin_name, plugin_version, plugin_author, plugin_description, plugin_maturity from information_schema.plugins where plugin_type = 'DAEMON';
сгенерирует следующий файл:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Created by CONNECT Version 3.05.0005 August 17, 2012 -->
<TABLE border="1" cellpadding="5">
<TR bgcolor="yellow">
<TH>handler</TH>
<TH>version</TH>
<TH>author</TH>
<TH>description</TH>
<TH>maturity</TH>
</TR>
<TR>
<TD>Maria</TD>
<TD>1.5</TD>
<TD>Monty Program Ab</TD>
<TD>Compatibility aliases for the Aria engine</TD>
<TD>Gamma</TD>
</TR>
</TABLE>
Этот файл можно использовать для отображения таблицы в веб-браузере (кодировка должна быть ISO-8859-x).
| Обработчик | Версия | Автор | Описание | Статус |
|---|---|---|---|---|
| Maria | 1.5 | Monty Program Ab | Псевдонимы совместимости для движка Aria | Гамма |
Примечание: Кодировка XML-документа обычно указывается в узле заголовка XML и может отличаться от DATA_CHARSET, который всегда UTF-8 для XML-таблиц. Поэтому настройка набора символов таблицы DATA_CHARSET должна быть не указана или указана как UTF8. Указание кодировки полезно только для новых XML-файлов и игнорируется для существующих файлов, имеющих уже заданную в узле заголовка кодировку.
Примечания
- ↑ CONNECT не претендует на возможность обработки любых XML-документов. Кроме того, те, которые могут быть полезно обработаны для анализа данных, вероятно, имеют структуру, которая легко может быть преобразована в таблицу.
- ↑ С помощью libxml2 текст подтегов может быть разделен 0 или несколькими пробелами в зависимости от структуры и отступов файла данных.
- ↑ Это может привести к потере некоторых строк, так как условное выражение where по столбцу «много» применяется только к ограниченному числу полученных строк.
© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/connect-xml-table-type/