Формирование xml произвольной структуры — различия между версиями

Материал из Oktell
Перейти к: навигация, поиск
 
(не показано 18 промежуточных версии этого же участника)
Строка 1: Строка 1:
FOR XML EXPLICIT
+
[[Работа с БД Oktell|Наверх]]
  
В данном режиме можно формировать практически любые документы; структура результирующего XML-документа определяется непосредственно в самом запросе. Запрос может принимать очень сложный вид, ниже будут рассмотрены правила, по которым он составляется.
+
__TOC__
  
Первое поле всегда называется tag и представляет собой числовой идентификатор таблицы. Вы можете указывать для него любые числовые значения. В результирующем документе он не появляется, и нужен только, чтобы определить связи между таблицами для формирования иерархического документа. Второе поле называется parent и тоже может представлять любой числовой идентификатор. Он определяет родительскую таблицу для данной таблицы и в результирующем документе также не присутствует. Если родитель отсутствует, указывается 0 или NULL. Для иерархических выборок нужно использовать несколько запросов, объединенных с помощью оператора UNION ALL.
+
==Введение==
 +
В данной статье будет рассмотрено формирование xml структур. Необходимость в данном механизме возникает как правило из-за требований сторонних систем, либо когда необходимо вернуть массив данных в сценарии Oktell (Oktell может получать только набор столбцов одной строки).  
 +
Для этого будем использовать один из режимов для FOR XML, более подробно Вы можете ознакомиться по ссылкам:
 +
*[https://msdn.microsoft.com/ru-ru/library/ms189068(v=sql.105).aspx Использование режима EXPLICIT]
 +
*[https://msdn.microsoft.com/ru-ru/library/bb522512(v=sql.105).aspx Конструирование одноуровневых элементов в режиме EXPLICIT]
  
После двух обязательных полей tag и parent следуют поля, которые требуется выбрать из таблицы. Для них должен быть задан псевдоним, определяющий тип XML-узла, его название и другую информацию. Вот синтаксис этого псевдонима:
+
==Режим FOR XML EXPLICIT==
 +
 
 +
Режим EXPLICIT предоставляет наибольшую гибкость при формировании желаемого XML из результатов запроса.
 +
Запрос в режиме EXPLICIT должен быть написан особым способом, при котором в запросе явно задаются дополнительные сведения о требуемом XML, такие как ожидаемый уровень вложенности в XML. В зависимости от запрашиваемого XML написание запросов режима EXPLICIT может оказаться весьма трудоемким. Может оказаться, что использование режима PATH с вложениями является более простой альтернативой написанию запросов в режиме EXPLICIT.
 +
 
 +
Режим EXPLICIT преобразует набор строк, получаемый в результате выполнения запроса, в XML-документ. Для того чтобы режим EXPLICIT создал XML-документ, набор строк должен иметь определенный формат. То есть необходимо написать запрос SELECT для создания набора строк, универсальной таблицы, имеющей определенный формат, так чтобы логика обработки могла создать желаемый XML.
 +
Во-первых, запрос должен создавать следующие два столбца метаданных:
 +
первый столбец должен предоставлять номер тега текущего элемента (целочисленного типа), и этот столбец должен иметь имя Tag. В запросе должен быть указан уникальный номер тега для каждого элемента, который будет создан из набора строк;
 +
второй столбец должен задавать номер тега для родительского элемента, и этот столбец должен иметь имя Parent. Таким образом, столбцы Tag и Parent предоставляют сведения об иерархии.
 +
Значения этих столбцов метаданных вместе со сведениями в именах столбцов используются для создания желаемого XML. Обратите внимание на то, что имена столбцов в запросе должны задаваться особым образом. Также обратите внимание на то, что значение 0 или NULL в столбце Parent указывает на то, что у соответствующего элемента нет родителя. Такой элемент добавляется в XML в качестве элемента верхнего уровня.
 +
 
 +
 
 +
При написании запросов в режиме EXPLICIT имена столбцов в результирующем наборе строк должны быть заданы с использованием описанного далее формата. Они предоставляют сведения о преобразовании, включая имена элементов и атрибутов и другие дополнительные сведения, задаваемые при помощи директив.
 +
Общий формат имеет вид:
  
 
  ElementName!TagNumber!AttributeName!Directive
 
  ElementName!TagNumber!AttributeName!Directive
  
Рассмотрим назначение каждой из частей этого псевдонима:
 
  
*ElementName – имя элемента, в котором будет находится элемент данного поля. Обычно здесь указывается имя таблицы.
+
,где
*TagNumber – идентификатор таблицы, в которой находится данное поле. Одному и тому же ElementName всегда должен соответствовать один TagNumber. Он также не отображается ни в каком виде в результирующем документе, однако нужен для определения иерархических связей между таблицами.
+
*ElementName - Результирующий общий идентификатор элемента. Например, если Customers задано в качестве ElementName, формируется элемент <Customers>.
*AttributeName имя атрибута (или элемента), представляющего данное поле.
+
*TagNumber - Уникальное значение тега, присвоенное элементу. Это значение с помощью двух метастолбцов, Tag и Parent, определяет вложенность элементов в результирующем XML.
*Directive – по существу, представляет собой тип узла. Может принимать следующие значения:
+
*AttributeName - Предоставляет имя создаваемого атрибута для указанного элемента ElementName. Это поведение используется, если не задано значение Directive. Если задано значение Directive, имеющее тип xml, cdata или element, оно используется для создания дочернего элемента ElementName, к которому добавляется значение столбца. При указании значения Directive значение AttributeName может быть пустым. Например: ElementName!TagNumber!!Directive. В этом случае значение столбца напрямую содержится в ElementName.
**element - поле представляется в виде элемента
+
*Directive - Значение Directive является необязательным и может использоваться для предоставления дополнительных сведений для создания XML.
**xml - То же самое, что element, но не выполняет трансформации текста. Например, символ меньше (<) не превращается в ссылку &lt;
+
 
**cdata - значение поля обрамляется соответствующим образом. Имя атрибута указывать совместно с этим ключевым словом нельзя.
+
 
**hide - позволяет скрыть поле
+
==Пример==
**id,idref,idrefs - позволяют делать ссылки на другие элементы. Эти атрибуты имеют значение, только если создается схема данных.
+
 
 +
Для примера сформируем xml структуру из таблицы oktell_settings.dbo.a_users из столбца [name]
 +
 
 +
 
 +
[[Файл:rand_xml.jpg|center|1000px]]
 +
 
 +
 
 +
 
 +
<span style="color:red">ВНИМАНИЕ: При конструировании XML строки в универсальной таблице обрабатываются по порядку. Поэтому для получения правильных экземпляров потомков, связанных с их родителями строки в наборе строк должны быть упорядочены так, чтобы за каждым родительским узлом следовали его потомки (Сначала select 1 далее select 2.1 и последний select 3.1, изменение порядка повлечет создание другой xml структуры либо ошибку).</span>
 +
 
 +
Разберем результат:
 +
 
 +
1)Существует элемент верхнего уровня (на рис. выделен зеленым цветом и цифрой 1), у которого 1 - tag и 0 - parent.
 +
 
 +
Для данного элемента перечислены столбцы sql запроса со следующими именами
 +
*ElementName=request
 +
*TagNumber=1
 +
*AttributeName = для разных столбцов - id,date или request_type. Данные имена атрибутов перечислены в request, за исключением id, т.к. его значение null, данный атрибут может понадобиться при наличии нескольких request.
 +
*Directive - отсутствует
 +
 
 +
2)Следующий элемент (на рис. выделен розовым цветом и цифрой 2) задается именем столбца указанном в 2 и содержит описание 2.1, у элемента 2 - tag и 1 - parent. Таким образом элемент request является для него родителем.
 +
 
 +
Для данного элемента перечислены столбцы sql запроса со следующими именами
 +
*ElementName=person_data
 +
*TagNumber=2
 +
*AttributeName = отсутствует
 +
*Directive - отсутствует
 +
 
 +
3)Последний элемент (на рис. выделен оранжевым цветом и цифрой 3) задается именем столбца указанном в 3 и содержит описание 3.1, у элемента 3 - tag и 2 - parent. Таким образом элемент person_data является для него родителем.
 +
 
 +
Для данного элемента перечислены столбцы sql запроса со следующими именами
 +
*ElementName=person
 +
*TagNumber=3
 +
*AttributeName = для разных столбцов:
 +
**record_id - используется функция row_number() over (order by name) отображения id записи
 +
**hash_last_name - значение name из таблицы oktell_settings.dbo.a_users
 +
*Directive - отсутствует
 +
 
 +
 
 +
 
 +
 
 +
Текст запроса:
 +
 
 +
<pre>
 +
select 1 as tag,
 +
      0 as parent,
 +
  null as [request!1!id],
 +
  getdate() as [request!1!date],
 +
  'Тип запроса' as [request!1!request_type],
 +
  null as [person_data!2!],
 +
  null  as [person!3!record_id],
 +
  null as [person!3!hash_last_name]
 +
 
 +
union all
 +
 
 +
select 2 as tag,
 +
      1 as parent,
 +
  null,
 +
  null,
 +
  null,
 +
  null,
 +
  null,
 +
  null
 +
 
 +
union all
 +
 
 +
select 3 as tag,
 +
      2 as parent,
 +
  null,
 +
  null,
 +
  null,
 +
  null,
 +
      row_number() over (order by name),
 +
  name
 +
from oktell_settings.dbo.a_users
 +
 
 +
for xml explicit
 +
</pre>
 +
 
 +
 
 +
Данный запрос вы можете использовать для тренировки и построить xml структуры различного вида.

Текущая версия на 12:06, 27 июля 2015

Наверх

Введение

В данной статье будет рассмотрено формирование xml структур. Необходимость в данном механизме возникает как правило из-за требований сторонних систем, либо когда необходимо вернуть массив данных в сценарии Oktell (Oktell может получать только набор столбцов одной строки). Для этого будем использовать один из режимов для FOR XML, более подробно Вы можете ознакомиться по ссылкам:

Режим FOR XML EXPLICIT

Режим EXPLICIT предоставляет наибольшую гибкость при формировании желаемого XML из результатов запроса. Запрос в режиме EXPLICIT должен быть написан особым способом, при котором в запросе явно задаются дополнительные сведения о требуемом XML, такие как ожидаемый уровень вложенности в XML. В зависимости от запрашиваемого XML написание запросов режима EXPLICIT может оказаться весьма трудоемким. Может оказаться, что использование режима PATH с вложениями является более простой альтернативой написанию запросов в режиме EXPLICIT.

Режим EXPLICIT преобразует набор строк, получаемый в результате выполнения запроса, в XML-документ. Для того чтобы режим EXPLICIT создал XML-документ, набор строк должен иметь определенный формат. То есть необходимо написать запрос SELECT для создания набора строк, универсальной таблицы, имеющей определенный формат, так чтобы логика обработки могла создать желаемый XML. Во-первых, запрос должен создавать следующие два столбца метаданных: первый столбец должен предоставлять номер тега текущего элемента (целочисленного типа), и этот столбец должен иметь имя Tag. В запросе должен быть указан уникальный номер тега для каждого элемента, который будет создан из набора строк; второй столбец должен задавать номер тега для родительского элемента, и этот столбец должен иметь имя Parent. Таким образом, столбцы Tag и Parent предоставляют сведения об иерархии. Значения этих столбцов метаданных вместе со сведениями в именах столбцов используются для создания желаемого XML. Обратите внимание на то, что имена столбцов в запросе должны задаваться особым образом. Также обратите внимание на то, что значение 0 или NULL в столбце Parent указывает на то, что у соответствующего элемента нет родителя. Такой элемент добавляется в XML в качестве элемента верхнего уровня.


При написании запросов в режиме EXPLICIT имена столбцов в результирующем наборе строк должны быть заданы с использованием описанного далее формата. Они предоставляют сведения о преобразовании, включая имена элементов и атрибутов и другие дополнительные сведения, задаваемые при помощи директив. Общий формат имеет вид:

ElementName!TagNumber!AttributeName!Directive


,где

  • ElementName - Результирующий общий идентификатор элемента. Например, если Customers задано в качестве ElementName, формируется элемент <Customers>.
  • TagNumber - Уникальное значение тега, присвоенное элементу. Это значение с помощью двух метастолбцов, Tag и Parent, определяет вложенность элементов в результирующем XML.
  • AttributeName - Предоставляет имя создаваемого атрибута для указанного элемента ElementName. Это поведение используется, если не задано значение Directive. Если задано значение Directive, имеющее тип xml, cdata или element, оно используется для создания дочернего элемента ElementName, к которому добавляется значение столбца. При указании значения Directive значение AttributeName может быть пустым. Например: ElementName!TagNumber!!Directive. В этом случае значение столбца напрямую содержится в ElementName.
  • Directive - Значение Directive является необязательным и может использоваться для предоставления дополнительных сведений для создания XML.


Пример

Для примера сформируем xml структуру из таблицы oktell_settings.dbo.a_users из столбца [name]


Rand xml.jpg


ВНИМАНИЕ: При конструировании XML строки в универсальной таблице обрабатываются по порядку. Поэтому для получения правильных экземпляров потомков, связанных с их родителями строки в наборе строк должны быть упорядочены так, чтобы за каждым родительским узлом следовали его потомки (Сначала select 1 далее select 2.1 и последний select 3.1, изменение порядка повлечет создание другой xml структуры либо ошибку).

Разберем результат:

1)Существует элемент верхнего уровня (на рис. выделен зеленым цветом и цифрой 1), у которого 1 - tag и 0 - parent.

Для данного элемента перечислены столбцы sql запроса со следующими именами

  • ElementName=request
  • TagNumber=1
  • AttributeName = для разных столбцов - id,date или request_type. Данные имена атрибутов перечислены в request, за исключением id, т.к. его значение null, данный атрибут может понадобиться при наличии нескольких request.
  • Directive - отсутствует

2)Следующий элемент (на рис. выделен розовым цветом и цифрой 2) задается именем столбца указанном в 2 и содержит описание 2.1, у элемента 2 - tag и 1 - parent. Таким образом элемент request является для него родителем.

Для данного элемента перечислены столбцы sql запроса со следующими именами

  • ElementName=person_data
  • TagNumber=2
  • AttributeName = отсутствует
  • Directive - отсутствует

3)Последний элемент (на рис. выделен оранжевым цветом и цифрой 3) задается именем столбца указанном в 3 и содержит описание 3.1, у элемента 3 - tag и 2 - parent. Таким образом элемент person_data является для него родителем.

Для данного элемента перечислены столбцы sql запроса со следующими именами

  • ElementName=person
  • TagNumber=3
  • AttributeName = для разных столбцов:
    • record_id - используется функция row_number() over (order by name) отображения id записи
    • hash_last_name - значение name из таблицы oktell_settings.dbo.a_users
  • Directive - отсутствует



Текст запроса:

select 1 as tag,
       0 as parent,
	   null as [request!1!id],
	   getdate() as [request!1!date],
	   'Тип запроса' as [request!1!request_type],
	   null as [person_data!2!],
	   null  as [person!3!record_id],
	   null as [person!3!hash_last_name]

union all

select 2 as tag,
       1 as parent,
	   null,
	   null,
	   null,
	   null,
	   null,
	   null

union all

select 3 as tag,
       2 as parent,
	   null,
	   null,
	   null,
	   null,
       row_number() over (order by name),
	   name
from oktell_settings.dbo.a_users

for xml explicit


Данный запрос вы можете использовать для тренировки и построить xml структуры различного вида.