Извлечение требуемого параметра типа имени из xml, хранящегося в таблице SQL - PullRequest
0 голосов
/ 08 января 2019

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

Пожалуйста, найдите ниже XML для справки:

<FORM>
  <PAGES>
    <PAGE Title="Record Input Sheet">
      <FIELDS>
        <FIELD Name="ddlStatus" type="DropdownList" Caption="Status" required="true" id="Status">
          <PROPERTIES>
            <PROPERTY name="ID">ddlStatus</PROPERTY>
            <PROPERTY name="BackColor">lightyellow</PROPERTY>
            <PROPERTY name="Width">75</PROPERTY>
            <PROPERTY name="onchange">CategoryPopulate(' ')</PROPERTY>
            <PROPERTY name="CssClass">form-control</PROPERTY>
          </PROPERTIES>
          <LISTITEMS>
            <LISTITEM value="">Select</LISTITEM>
            <LISTITEM value="Adjudicate">Adjudicate</LISTITEM>
            <LISTITEM value="Skip">Skip</LISTITEM>
            <LISTITEM value="Cancel">Cancel</LISTITEM>
          </LISTITEMS>
        </FIELD>
      </FIELDS>
    </PAGE>
  </PAGES>
</FORM>

Я написал приведенный ниже код для извлечения свойств и элемента списка, но не смог извлечь параметры столбца:

select 
    [XmlFile].value('(/FORM/PAGES/PAGE/FIELDS/FIELD/PROPERTIES/PROPERTY)[1]','varchar(255)') ,
    [XmlFile].value('(/FORM/PAGES/PAGE/FIELDS/FIELD/PROPERTIES/PROPERTY)[2]','varchar(255)') ,
    [XmlFile].value('(/FORM/PAGES/PAGE/FIELDS/FIELD/PROPERTIES/PROPERTY)[3]','varchar(255)'),
    [XmlFile].value('(/FORM/PAGES/PAGE/FIELDS/FIELD/LISTITEMS/LISTITEM)[1]','varchar(255)') 
from 
    tbl_reference 
where  
    [QueueName] = 'ReferenceQueue'; 

1 Ответ

0 голосов
/ 08 января 2019

SQL-сервер имеет довольно расширенную поддержку для работы с XML. То, что вы ищете, это собственные методы XML типа данных XML .value(), .nodes() и .query(). Найти подробности здесь .

Попробуйте:

DECLARE @xml XML=
N'<FORM>
  <PAGES>
    <PAGE Title="Record Input Sheet">
      <FIELDS>
        <FIELD Name="ddlStatus" type="DropdownList" Caption="Status" required="true" id="Status">
          <PROPERTIES>
            <PROPERTY name="ID">ddlStatus</PROPERTY>
            <PROPERTY name="BackColor">lightyellow</PROPERTY>
            <PROPERTY name="Width">75</PROPERTY>
            <PROPERTY name="onchange">CategoryPopulate('' '')</PROPERTY>
            <PROPERTY name="CssClass">form-control</PROPERTY>
          </PROPERTIES>
          <LISTITEMS>
            <LISTITEM value="">Select</LISTITEM>
            <LISTITEM value="Adjudicate">Adjudicate</LISTITEM>
            <LISTITEM value="Skip">Skip</LISTITEM>
            <LISTITEM value="Cancel">Cancel</LISTITEM>
          </LISTITEMS>
        </FIELD>
      </FIELDS>
    </PAGE>
  </PAGES>
</FORM>';

SELECT pg.value('@Title','nvarchar(max)') AS PAGE_Title
      ,fld.value('@Name','nvarchar(max)') AS FIELD_Name
      ,fld.value('@type','nvarchar(max)') AS FIELD_type
      ,fld.value('@Caption','nvarchar(max)') AS FIELD_Caption
      ,fld.value('@required','nvarchar(max)') AS FIELD_required
      ,fld.value('@id','nvarchar(max)') AS FIELD_id
      ,fld.query('PROPERTIES/PROPERTY') AS FIELD_Properties
      ,fld.query('LISTITEMS/LISTITEM') AS FIELD_ListItems
FROM @xml.nodes('/FORM/PAGES/PAGE') A(pg)
OUTER APPLY A.pg.nodes('FIELDS/FIELD') B(fld);

Идея:

Вызов .nodes() на /FORM/PAGES/PAGE вернет производную таблицу со всеми страницами (если их несколько). Затем мы используем другой вызов .nodes(), чтобы получить производную таблицу всех полей под каждой страницей.

.value() -метод используется для получения внутренних значений. В вашем случае это атрибуты, следовательно, @.

Я не знаю, как вы хотите иметь дело с внутренними свойствами и элементами списка, поэтому я включил их просто как .

UPDATE

Согласно вашему комментарию, следующий запрос немного улучшен: свойства выбираются по их именам, а список элементов списка возвращается в виде строки, разделенной запятой.

SELECT pg.value('@Title','nvarchar(max)') AS PAGE_Title
      ,fld.value('@Name','nvarchar(max)') AS FIELD_Name
      ,fld.value('@type','nvarchar(max)') AS FIELD_type
      ,fld.value('@Caption','nvarchar(max)') AS FIELD_Caption
      ,fld.value('@required','nvarchar(max)') AS FIELD_required
      ,fld.value('@id','nvarchar(max)') AS FIELD_id
      ,fld.value('(PROPERTIES/PROPERTY[@name="ID"]/text())[1]','nvarchar(max)') AS Prop_ID
      ,fld.value('(PROPERTIES/PROPERTY[@name="BackColor"]/text())[1]','nvarchar(max)') AS Prop_BackColor
      --more properties--
      ,STUFF(
       fld.query('for $li in LISTITEMS/LISTITEM
                  return <x>{concat(",",$li/text()[1])}</x>
                 ').value('.','nvarchar(max)'),1,1,'') AS ListItems_separatedByBlanks
FROM @xml.nodes('/FORM/PAGES/PAGE') A(pg)
OUTER APPLY A.pg.nodes('FIELDS/FIELD') B(fld);

О свойствах:
Часть [@name="ID"] называется предикатом . Это фильтр XQuery, который можно прочитать как , взять свойство, где атрибут name равен ID и выбрать его text().

Об элементах списка:
Это небольшой взлом с использованием FLWOR-XQuery . Его можно прочитать как Выполнить через элементы списка и вернуть новый XML, где каждому text() предшествует запятая . Использование . в качестве Xpath в .value() вернет все из них в один . Функция STUFF() необходима только для удаления запятой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...