Попробуйте, как это:
DECLARE @yourTable TABLE(ID INT IDENTITY,Val XML);
INSERT INTO @yourTable VALUES
(N'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<ns0:getInterestAndExchangeRatesResponse xmlns:ns0="http://swea.riksbank.se/xsd">
<return xmlns="">
<datefrom xmlns="">2020-03-25</datefrom>
<dateto xmlns="">2020-03-26</dateto>
<groups xmlns="">
<groupid xmlns="">130</groupid>
<groupname xmlns="">Currencies against Swedish kronor</groupname>
<series xmlns="">
<seriesid xmlns="">SEKEURPMI</seriesid>
<seriesname xmlns="">1 EUR</seriesname>
<unit xmlns="">1.0E0</unit>
<resultrows xmlns="">
<date xmlns="">2020-03-25</date>
<period xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance" xmlns="" ns1:nil="true" />
<min xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance" xmlns="" ns1:nil="true" />
<average xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance" xmlns="" ns1:nil="true" />
<max xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance" xmlns="" ns1:nil="true" />
<ultimo xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance" xmlns="" ns1:nil="true" />
<value xmlns="">1.08823E1</value>
</resultrows>
</series>
</groups>
</return>
</ns0:getInterestAndExchangeRatesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>');
- запрос
SELECT t.ID
,A.gr.value('(groupid/text())[1]','int') AS groupId
,A.gr.value('(groupname/text())[1]','nvarchar(max)') AS groupName
,B.sr.value('(seriesid/text())[1]','nvarchar(max)') AS seriesId
,B.sr.value('(seriesname/text())[1]','nvarchar(max)') AS seriesName
,C.rw.value('(date/text())[1]','date') AS rowDate
,C.rw.value('(period/text())[1]','nvarchar(max)') AS rowPeriod
,C.rw.value('(value/text())[1]','float') AS rowValue
FROM @yourTable t
CROSS APPLY t.Val.nodes('//groups') A(gr)
OUTER APPLY A.gr.nodes('series') B(sr)
OUTER APPLY B.sr.nodes('resultrows') C(rw);
Идея вкратце и немного фона:
- Форма множественного числа
<groups>
, <series>
и <resultrows>
позволяют мне думать, что это вложенные, 1:n
связанные данные, следовательно, каскад из APPLY ...nods()
. - This XML есть беспорядок неправильных пространств имен ...
- Было бы ужасно уродливо правильно определять / объявлять все пространства имен ...
- Радостно, что значения живут в пустом пространстве имен по умолчанию.
- Чтобы избежать пространств имен, я начинаю с
//groups
. Двойной //
вызывает глубокий поиск. Не следуйте этому предложению, если элемент <groups>
может произойти где-либо еще! - Мы получаем все группы
- Мы получаем все серии в каждой группе
- Мы получаем все строки в каждом ser ie
Подсказка: о ns1:nil="true"
. Предполагается, что это было сгенерировано с T- SQL с использованием ELEMENTS XSINIL
. XML по умолчанию будет пропускать значения NULL. Это означает, что читатель должен знать схему. Запрос о пропущенном элементе вернет NULL. но в этом случае все элементы генерируются. Мы можем проверить, является ли атрибут nil
true
. Но в этом случае проще проверить узел text()
. Это отсутствует и будет неявно возвращать NULL.
Некоторые замечания о пространствах имен:
- Пространства имен для именования
SOAP
связанных частей в порядке, пространство имен для указания элемента <getInterestAndExchangeRatesResponse>
тоже хорошо. - Но часто используемый
xmlns=""
действительно странный. Это снова и снова будет определять пустое пространство имен по умолчанию ... - Я предполагаю, что оно генерируется с помощью T- SQL с использованием вложенных вызовов
FOR XML
и путем помещения такого предварительно сгенерированного содержимого XML в SOAP конверт.