Использование режима EXPLICIT с FOR XML

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

Как описано в статье, создание XML с помощью РЕЖИМА FOR XML, RAW и AUTO не обеспечивает много контроля над формой XML, созданной из результата запроса. Однако режим EXPLICIT предоставляет наибольшую гибкость при формировании желаемого XML из результатов запроса.

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

Поскольку требуемый XML описывается в режиме EXPLICIT в самом запросе, следует убедиться в том, что порождаемый XML имеет необходимую форму и является корректным.

Обработка набора строк в режиме EXPLICIT

Режим EXPLICIT преобразует набор строк, получаемый в результате выполнения запроса, в XML-документ. Для того чтобы режим EXPLICIT создал XML-документ, набор строк должен иметь определенный формат. То есть необходимо написать запрос SELECT для создания набора строк, универсальной таблицы, имеющей определенный формат, так чтобы логика обработки могла создать желаемый XML.

Во-первых, запрос должен создавать следующие два столбца метаданных:

  • первый столбец должен предоставлять номер тега текущего элемента (целочисленного типа), с именем столбца Tag. В запросе должен быть указан уникальный номер тега для каждого элемента, который будет создан из набора строк;

  • второй столбец должен задавать номер тега для родительского элемента, и этот столбец должен иметь имя Parent. Таким образом, столбцы Tag и Parent предоставляют сведения об иерархии.

Значения этих столбцов метаданных вместе со сведениями в именах столбцов используются для создания желаемого XML. Запрос должен предоставлять имена столбцов определенным образом. Также обратите внимание на то, что значение 0 или NULL в столбце Parent указывает на то, что у соответствующего элемента нет родителя. Такой элемент добавляется в XML в качестве элемента верхнего уровня.

Для понимания того, как универсальная таблица, сформированная запросом, преобразуется в результат XML, предположим, что написан запрос, который создает универсальную таблицу.

Пример универсальной таблицы.

Обратите внимание на следующие особенности этой универсальной таблицы:

  • Первые два столбца Tag и Parent являются метастолбцами. Эти значения определяют иерархию.

  • Имена столбцов указываются определенным образом, как описано далее в этой статье.

  • При формировании XML из этой универсальной таблицы данные таблицы секционируются вертикально на группы столбцов. Группировка определяется на основании значения Tag и имен столбцов. При конструировании XML логика обработки выбирает одну группу столбцов для каждой строки и создает элемент. В данном примере происходит следующее:

    • для значения столбца Tag , равного 1 в первой строке, столбцы, имена которых включают тот же номер тега, Customer!1!cid и Customer!1!name, образуют группу. Эти столбцы используются для обработки строки, и, возможно, вы заметили, что форма созданного элемента <Customer id=... name=...>. Формат имени столбца описан далее в этой статье.

    • Для строк со значением столбца тега 2 столбца Order!2!id и Order!2!date формирует группу, которая затем используется в конструкторе элементов. <Order id=... date=... />

    • для строк со значением столбца Tag , равным 3, столбцы OrderDetail!3!id!id и OrderDetail!3!pid!idref образуют группу. Каждая из этих строк создает элемент из <OrderDetail id=... pid=...>этих столбцов.

  • При создании XML-иерархии строки обрабатываются по порядку. Иерархия XML определяется так, как показано далее.

    • Первая строка задает значение Tag , равное 1, и значение Parent , равное NULL. Поэтому соответствующий элемент, <Customer> элемент, добавляется как элемент верхнего уровня в XML.

      <Customer cid="C1" name="Janine">
      
    • Вторая строка задает значение Tag , равное 2, и значение Parent , равное 1. Поэтому элемент, <Order> элемент, добавляется в качестве дочернего <Customer> элемента элемента.

      <Customer cid="C1" name="Janine">
         <Order id="O1" date="1/20/1996">
      
    • Следующие две строки задают значение Tag , равное 3, и значение Parent , равное 2. Поэтому два элемента, <OrderDetail> элементы, добавляются в качестве дочерних <Order> элементов элемента.

      <Customer cid="C1" name="Janine">
         <Order id="O1" date="1/20/1996">
            <OrderDetail id="OD1" pid="P1"/>
            <OrderDetail id="OD2" pid="P2"/>
      
    • Последняя строка задает 2 в качестве номера Tag и 1 в качестве номера тэга Parent . Поэтому в родительский элемент добавляется еще один <Order> дочерний <Customer> элемент.

      <Customer cid="C1" name="Janine">
         <Order id="O1" date="1/20/1996">
            <OrderDetail id="OD1" pid="P1"/>
            <OrderDetail id="OD2" pid="P2"/>
         </Order>
         <Order id="O2" date="3/29/1997">
      </Customer>
      

В итоге, значения в метастолбцах Tag и Parent , сведения, указанные в именах столбцов, и правильный порядок строк создают желаемый XML при использовании режима EXPLICIT.

Упорядочение строк универсальной таблицы

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

Указание имен столбцов в универсальной таблице

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

Общий формат имеет вид:

ElementName!TagNumber!AttributeName!Directive

Далее следует описание частей формата.

  • ElementName

    Результирующий универсальный идентификатор элемента. Например, если Customers задано в качестве ElementName, формируется элемент <Customers>.

  • TagNumber

    Уникальное значение тега, назначенное элементу. Это значение с помощью двух метастолбцов, Tag и Parent, определяет вложенность элементов в результирующем XML.

  • AttributeName

    Предоставляет имя создаваемого атрибута для указанного элемента ElementName. Это поведение, если директива не указана.

    Если задано значение Directive , имеющее тип xml, cdataили element, оно используется для создания дочернего элемента ElementName, к которому добавляется значение столбца.

    При указании значения Directiveзначение AttributeName может быть пустым. Например: ElementName!TagNumber!!Directive. В этом случае значение столбца напрямую содержится в ElementName.

  • Directive

    ЗначениеDirective является необязательным и может использоваться с целью предоставления дополнительных сведений для создания XML. ЗначениеDirective служит двум целям.

    • Одной из целей является кодирование значений в виде ID, IDREF и IDREFS. Можно указать ключевые слова ID, IDREFи IDREFS в качестве значений Directive. Эти директивы переопределяют типы атрибутов. Это позволяет создавать связи внутри документа.

    • Также можно использовать значение Directive для указания того, как сопоставлять строковые данные с XML. Ключевые слова hide, element, elementxsinil, xml, xmltextи cdata также могут быть использованы в качестве значения Directive. Директива hide скрывает узел. Это полезно при извлечении значений только в целях сортировки, но они не нужны в результирующем XML.

    Директива element формирует содержащийся элемент вместо атрибута. Содержащиеся данные кодируются как сущность. Например, символ < превращается в <. Для значений столбцов, равных NULL, элемент не формируется. Если требуется, чтобы для столбцов со значениями NULL формировался элемент, можно указать директиву elementxsinil . При этом будет сформирован элемент с атрибутом xsi:nil=TRUE.

    Директива xml аналогична директиве element , однако при ее использовании не происходит кодирования сущности. Директива элемента может сочетаться с ID, IDREF или IDREFS, а директива XML не допускается с какой-либо другой директивой, кроме скрытия.

    Директива cdata содержит данные путем упаковывания их с помощью раздела CDATA. Содержимое не закодировано. Первоначальный тип данных должен быть текстовым, например varchar, nvarchar, textили ntext. Эта директива может использоваться только совместно с hide. При использовании этой директивы не следует задавать значение AttributeName .

    Объединение директив между этими двумя группами допускается в большинстве случаев, но объединение их между собой не допускается.

Если директива и AttributeName не указаны, например Customer!1, то подразумевается директива элемента, например Customer!1!! элемент и данные столбца содержатся в элементе ElementName.

Если задана директива xmltext , содержимое столбца упаковывается в один тэг, который интегрируется с оставшейся частью документа. Эта директива полезна при выборке перегруженных, неиспользуемых XML-данных, сохраненных в столбец при помощи OPENXML. Дополнительные сведения см. в разделе OPENXML (SQL Server).

Если задано значение AttributeName , имя тега заменяется указанным именем. В противном случае атрибут добавляется к текущему списку атрибутов включаемых элементов путем помещения содержимого в начало содержимого без кодирования сущности. Столбец с этой директивой должен быть текстового типа, например varchar, nvarchar, char, nchar, textили ntext. Эта директива может использоваться только совместно с hide. Эта директива полезна при выборке перегруженных данных, хранящихся в столбце. Если содержимое не является хорошо сформированным XML, поведение не определено.

Следующие шаги

В следующем примере демонстрируется применение режима EXPLICIT.

См. также