Конвертировать пары ключ-значение XML в строку - PullRequest
0 голосов
/ 04 июня 2019

У меня есть этот запрос:

SELECT 
    XMLColumn.i.query('.') AS XMLColumn, 
    ID
FROM
    MyTable
CROSS APPLY 
    MyTable.XMLColumn.nodes('Root/Fields') AS Col(i)

, который возвращает этот результат:

╔═════════════════════════╦════╗
║        XMLColumn        ║ ID ║
╠═════════════════════════╬════╣
║ <Fields>                ║  1 ║
║   <Field>               ║    ║
║     <Name>First</Name>  ║    ║
║     <Value>1</Value>    ║    ║
║   </Field>              ║    ║
║   <Field>               ║    ║
║     <Name>Second</Name> ║    ║
║     <Value>2</Value>    ║    ║
║   </Field>              ║    ║
║   <Field>               ║    ║
║     <Name>Third</Name>  ║    ║
║     <Value>3</Value>    ║    ║
║   </Field>              ║    ║
║ </Fields>               ║    ║
╚═════════════════════════╩════╝

Есть ли способ преобразовать эту структуру XML в следующий формат строки?

╔══════════════════════════╦════╗
║        XMLColumn         ║ ID ║
╠══════════════════════════╬════╣
║ First=1;Second=2;Third=3 ║  1 ║
╚══════════════════════════╩════╝

Ответы [ 2 ]

2 голосов
/ 05 июня 2019

Это чистый подход XQuery

DECLARE @x XML = 
N'<Fields>
   <Field>
      <Name>First</Name>
      <Value>1</Value>
   </Field>
   <Field>
      <Name>Second</Name>
      <Value>2</Value>
   </Field>
   <Field>
      <Name>Third</Name>
      <Value>3</Value>
   </Field>
</Fields>';

- запрос

SELECT STUFF(
@x.query
('
    for $fld in /Fields/Field
    return <x>{concat(";"
                     ,($fld/Name/text())[1]
                     ,"="
                     ,($fld/Value/text())[1])
               }</x>
').value('.','nvarchar(max)'),1,1,'');

Идея вкратце:

Мы перебираем все поля и создаем совершенно новый XML этого формата

<x>;First=1</x>
<x>;Second=2</x>
<x>;Third=3</x>

Использование .value() с . в качестве XPath вернет весь контент (без тегов) в виде строки. STUFF() используется, чтобы отрезать ведущий ;.

1 голос
/ 04 июня 2019

Вы можете использовать .nodes и .value Методы типа данных XML , чтобы получить значения элементов из XML, а затем использовать трюк SQL Server FOR XML, чтобы объединить значения в строку с разделителями. Результат этого кода включает в себя конечный разделитель - это может или не может соответствовать вашим потребностям.

declare @x xml = '<Fields>
   <Field>
      <Name>First</Name>
      <Value>1</Value>
   </Field>
   <Field>
      <Name>Second</Name>
      <Value>2</Value>
   </Field>
   <Field>
      <Name>Third</Name>
      <Value>3</Value>
   </Field>
</Fields>'

-- Use .nodes and .value methods to get the element values as a rowset.
select
    c.value('Name[1]', 'varchar(100)'),
    c.value('Value[1]', 'int')
from
    @x.nodes('/Fields/Field') as T(c)

-- Use the FOR XML trick to concatenate the values.
select c.value('Name[1]', 'varchar(100)') + '=' + c.value('Value[1]', 'varchar(20)') + ';' AS [text()]
from @x.nodes('/Fields/Field') as T(c)
for xml path ('')
...