Автоматический ввод-вывод XML в IDEF1-хранилище
03.09.2010
—
Новости Hi-Tech
|
XML имеет смысл только как коммуникационный протокол, хранить его - большая ошибка, подробнее вы можете ознакомиться с рассуждениями на Первое, xml-элемент записывается в одноименную таблицу (т.е. имя тега совпадает с именем таблицы), xml-атрибут - в одноименное поле (имя атрибута совпадает с именем поля). Первичный ключ новой записи заполняется триггером. Второе, во время создания двух записей, соответствующих родительскому и дочернему xml-элементам, первичный ключ одной копируется во внешний ключ другой. В случае неоднозначности из-за того, что одна таблица ссылается на другую несколькими внешними ключами или две таблицы ссылаются друг на друга одновременно, неоднозначность разрешается в имени открывающего xml-тега: после, собственно, имени тега ставится знак # и имя нужного ссылающегося поля. Выглядит как новое имя открывающего тега с символом # в середине имени (с.81-83). Закрывающий тег остается без изменений. Будем называть это детерминацией. Третье, одноименные и не вложенные, а последовательно расположенные xml-элементы превращаются в список записей, т.е. первичный ключ одной записи также копируется во внешний ключ другой. Если таблица ссылается на саму себя несколькими внешними ключами, то неоднозначность также разрешается в имени открывающего xml-тега, только вместо знака # ставится $ (закрывающий тег также остается без изменений). И это также будем называть детерминацией (с.84-85). Примем, что детерминация должна быть указана в каждом из последовательно расположенных одноименных xml-элементов - чтобы пользователю меньше думать. Мы применяем разные знаки - # и $ - чтобы оба вида детерминации можно было использовать одновременно, например, tag#field1$field2 Обратная задача - вывод записей в xml-виде. Использование функций SQL/XML, XQuery, проприетарных веб-серверов (относительно последних подробнее на Если одна таблица ссылается на другую несколькими внешними ключами или две таблицы ссылаются друг на друга одновременно, то после имени таблицы ставится знак # и имя нужного ссылающегося поля. Будем называть это рафинированием. Выглядит как имя таблицы с символом # в середине имени (с.12-14). Аналогично, если таблица, содержащая список, ссылается на саму себя несколькими внешними ключами, то после имени таблицы ставится знак $ и имя нужного ссылающегося поля. Это также будем называть рафинированием (с.15-16). Оба вида рафинирования можно использовать одновременно, например, table#field1$field2. Как записать детерминацию и рафинирование при нескольких ссылающихся полях? Перечислим ситуации. Распорка (nog) - соединение двумя внешними ключами трех таблиц, причем ссылающиеся поля находятся в одной промежуточной таблице. create table a ( id num primary key, data float ); create table b ( id num primary key, ref1 num references a(id), - нужно ref2 num references a(id), - не нужно ref3 num references c(id), - нужно ref4 num references c(id), - не нужно data float ); create table c ( id num primary key, data float ); И в детерминации, и в рафинировании ссылающиеся поля указываются через двоеточие; таблица-предок упоминается первой, потомок - второй (ссылающиеся поля могут быть одноименными). Таким образом, ввод выглядит как <a> <b#ref1:ref3> <c> </b> </a> вывод (XTree) как a.b#ref1:ref3.c, а маршрут по схеме к нужной таблице (XPath) как a/b#ref1:ref3/c Стяжка (buckle) - также два ключа с тремя таблицами, но ссылающиеся поля ссылаются на промежуточную таблицу. create table a ( id num primary key, ref1 num references b(id), - нужно ref2 num references b(id), - не нужно data float ); create table b ( id num primary key, data float ); create table c ( id num primary key, ref1 num references b(id), - нужно ref2 num references b(id), - не нужно data float ); Соответственно, ввод <a#ref1> <b> <c#ref3> </b> </a> вывод a#ref1.b.c#ref3, маршрут a#ref1/b/c#ref3. Перекрёсток (crossroad) мы имеем, когда таблиц всего две. create table a ( id num primary key, ref num references b(id), data float ); create table b ( id num primary key, lnk num references a(id), data float ); В этом случае мы можем полагать родительской таблицей как одну, так и другую. Поэтому ввести можно двумя способами: <a#ref> <b> </a> и <a> <b#lnk> </a> XTree и XPath также две пары a#ref.b, a#ref/b и a.b#lnk, a/b#lnk. А вот ситуация из трех таблиц, две из которых - потомки третьей, имеет две разновидности, в зависимости от того, родительская ссылается на дочерние или наоборот. Обе будем называть разветвлением (branching), но сначала рассмотрим ситуацию, когда ссылаются дочерние. create table a ( id num primary key, data float ); create table b ( id num primary key, ref1 num references a(id), - нужно ref2 num references a(id), - не нужно data float ); create table c ( id num primary key, ref1 num references a(id), - нужно ref2 num references a(id), - не нужно data float ); Входящий XML выглядит как <a> <b#ref1> <c#ref1> </a> а вот XTree и XPath имеют два варианта, ведь предикат может требовать дерево как со всеми ветвями, так и только с одной. Со всеми - это a.(b#ref1 c#ref1) и a/(b#ref1 c#ref1). А вот с одной существует только XTree, т.е. a.(b#ref1 | c#ref1), т.к. в случае a/(b#ref1 | c#ref1) не понятно, какой марштут брать. Теперь рассмотрим ситуацию, когда ссылается родительская таблица. create table a ( id num primary key, ref1 num references b(id), - нужно ref2 num references b(id), - не нужно ref3 num references c(id), - нужно ref4 num references c(id), - не нужно data float ); create table b ( id num primary key, data float ); create table c ( id num primary key, data float ); Здесь ввод <a#ref1+ref3> <b> <c> </a> вывод и маршрут с требованием записей во всех дочерних таблицах есть a#ref1+ref3.(b c) и a#ref1+ref3/(b c). Аналогично в случае, если достаточно только одной дочерней записи, существует XTree, т.е. a#ref1^ref3.(b | c), но не существует XPath. Обратили внимание, что стоит #ref1^ref3, а не #ref1+ref3 ? Этим мы избегаем когнитивного диссонанса между 'или', обозначаемом вертикальной чертой, и плюсиком. Своеобразной инверсией разветвления является продолжение (continuation) - ситуация, в которой одна таблица одновременно является потомком двух других. Здесь ввода нет вообще! Потому что xml-элемент не может быть потомком двух других (специальные изголения для программистов оставим этим последним). Однако вывод существует, ведь можно одну запись извлечь дважды - как дочернюю двух разных родительских. У продолжения, опять же, две разновидности, и сначала рассмотрим ту, в которой ссылаются дочерние таблицы. create table b ( id num primary key, data float ); create table c ( id num primary key, data float ); create table d ( id num primary key, ref1 num references b(id), - нужно ref2 num references b(id), - не нужно ref3 num references c(id), - нужно ref4 num references c(id), - не нужно data float ); Чтобы работа происходила, только если существуют все возможные xml-деревья, мы пишем .(b.d#ref1 c.d#ref3). и /(b/d#ref1 c/d#ref3)/ ; если существует хотя бы одно дерево /(b/d#ref1 | c/d#ref3)/. Теперь рассмотрим ситуацию, когда ссылается родительская таблица. create table b ( id num primary key, ref1 num references d(id), - нужно ref2 num references d(id), - не нужно data float ); create table c ( id num primary key, ref1 num references d(id), - нужно ref2 num references d(id), - не нужно data float ); create table d ( id num primary key, data float ); Ну, в общем-то все то же самое - в смысле .(b#ref1 c#ref3).d., /(b#ref1 c#ref3)/d/ и .(b#ref1 | c#ref3).d. Во всех ситуациях ссылающиеся поля составных внешних ключей будем перечислять через знак умножения. Во вводе это выглядит как <a> <b#lnk1*lnk2> </a> в выводе и маршруте - как a.b#lnk1*lnk2 и a/b#lnk1*lnk2. Наши предложения позволяют именно простому пользователю делать репликацию и аггрегировать информацию из множества источников. Прозрачный, без участия программиста ввод-вывод иерархических данных сохранит актуальность даже в следующей эпохе, когда все HTTP, FTP, SMTP/POP3, FE/BE и прочие со всеми их ETL-ами будут заменены единым протоколом и форматом, а каждая передача данных будет копированием записей или обновлением полей хранилища - как это описано, например, в статье "Ошибки и их исправление в эргономике API и GUI" ("КВ" № Дмитрий ТЮРИН, Чтобы разместить новость на сайте или в блоге скопируйте код:
На вашем ресурсе это будет выглядеть так
XML имеет смысл только как коммуникационный протокол, хранить его - большая ошибка... |
|