Openxml выбирает данные из сложного xml с префиксом

Структура XML и ожидаемый результат приведены ниже, я могу просмотреть все данные, но не могу выбрать элементы xml из xpath, поскольку узел item имеет префикс «a:»

Я пробовал следующее, но никто не работает:

№1:

        Set @path =  N'/root/JSON/schData/ESU/item[1]/ESU_Bl_0'
        SELECT * from openxml (@hDoc, @path, 2)
        with            
        (   
             ID         nvarchar(200) 
            ,Item_0_1   nvarchar(200) 
            ,Item_0_2   nvarchar(200) 
        )

№2:

        Set @path =  N'/root/JSON/schData/ESU/a:item/ESU_Bl_0'
        SELECT * from openxml (@hDoc, @path, 2)
        with            
        (   
             ID         nvarchar(200) 
            ,Item_0_1   nvarchar(200) 
            ,Item_0_2   nvarchar(200) 
        )

№3:

        Set @path =  N'/root/JSON/schData/ESU//*:item/ESU_Bl_0'
        SELECT * from openxml (@hDoc, @path, 2)
        with            
        (   
             ID         nvarchar(200) 
            ,Item_0_1   nvarchar(200) 
            ,Item_0_2   nvarchar(200) 
        )

№4:

        Set @path =  N'/root/JSON/schData/ESU/a[1]/ESU_Bl_0'
        SELECT * from openxml (@hDoc, @path, 2)
        with            
        (   
             ID         nvarchar(200) 
            ,Item_0_1   nvarchar(200) 
            ,Item_0_2   nvarchar(200) 
        )

Пожалуйста, помогите своим опытом, спасибо !!

ОБНОВЛЕНИЕ: образец xml, как указано в комментарии -

<root type = "object">
    <JSON type = "object">
        <schData type = "object">
            <ESU type = "object">
                <a:item xmlns:a = "item" item = "0" type = "object">
                    <ESU_Bl_0 type = "object">
                        <ID type = "number">1</ID>
                        <Item_0_1 type = "string">A</Item_0_1>
                        <Item_0_2 type = "string">B</Item_0_2>
                    </ESU_Bl_0>
                    <ESU_Bl_1 type = "object">
                        <ID type = "number">2</ID>
                        <Item_1_1 type = "string">C</Item_1_1>
                        <Item_1_2 type = "string">D</Item_1_2>
                    </ESU_Bl_1>
                </a:item>
                <a:item xmlns:a = "item" item = "1" type = "object">
                    <ESU_Bl_0 type = "object">
                        <ID type = "number">3</ID>
                        <Item_0_1 type = "string">E</Item_0_1>
                        <Item_0_2 type = "string">F</Item_0_2>
                    </ESU_Bl_0>
                    <ESU_Bl_1 type = "object">
                        <ID type = "number">4</ID>
                        <Item_1_1 type = "string">G</Item_1_1>
                        <Item_1_2 type = "string">H</Item_1_2>
                    </ESU_Bl_1>
                </a:item>
            </ESU>
        </schData>
    </JSON>
</root>

ОБНОВЛЯТЬ:

Решение, предложенное Ицхаком, подходит для статического запроса, но когда я пытаюсь динамически ввести переменную Counter, я получаю следующую ошибку.

Line 41 [Batch Start Line 0]
The argument 1 of the XML data type method "nodes" must be a string literal.

Вот как я пытаюсь:

;WITH XMLNAMESPACES('item' AS a)
SELECT c.value('(ID/text())[1]', 'INT') AS ID
    , c.value('(Item_0_1/text())[1]', 'VARCHAR(20)') AS Item_0_1
    , c.value('(Item_0_2/text())[1]', 'VARCHAR(20)') AS Item_0_2
FROM @xml.nodes('/root/JSON/schData/ESU/a:item[@item = "'+@Counter+'"]/ESU_Bl_0') AS t(c);

Отправьте xml в виде текста, а не изображения.

David Browne - Microsoft 23.12.2022 19:23

Задавая вопрос, вы должны предоставить минимальный воспроизводимый пример: (1) DDL и выборочное заполнение данных, т. е. таблицы CREATE плюс операторы INSERT T-SQL. (2) Что вам нужно сделать, т. е. логика и ваш код попытаются реализовать ее в T-SQL. (3) Желаемый результат, основанный на примерных данных в # 1 выше. (4) Ваша версия SQL Server (SELECT @@version;). Все в рамках вопроса, без изображений.

Yitzhak Khabinsky 23.12.2022 19:23

Привет, @DavidBrowne-Microsoft, добавил XML. Спасибо.

Bilal Siddiqui 23.12.2022 19:26

Ваш XML неправильно сформирован. "Ошибка синтаксического анализа в Untitled2.xml: ожидаемый конец тега Item_1_1" Пожалуйста, исправьте.

Yitzhak Khabinsky 23.12.2022 19:30

@YitzhakKhabinsky, исправлено, извините, xml был слишком большим, при уменьшении я допустил эту ошибку.

Bilal Siddiqui 23.12.2022 19:31

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

Dale K 23.12.2022 21:55
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
6
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пожалуйста, попробуйте следующее решение.

Собственный Microsoft OPENXML() и его компаньоны sp_xml_preparedocument и sp_xml_removedocument сохранены только для обратной совместимости с устаревшим SQL. Server 2000. Их использование сведено к очень небольшому количеству крайних случаев. Начиная с SQL Server 2005 и далее, настоятельно рекомендуется переписать ваш SQL и переключиться на XQuery.

SQL

DECLARE @xml XML =
N'<root type = "object">
    <JSON type = "object">
        <schData type = "object">
            <ESU type = "object">
                <a:item xmlns:a = "item" item = "0" type = "object">
                    <ESU_Bl_0 type = "object">
                        <ID type = "number">1</ID>
                        <Item_0_1 type = "string">A</Item_0_1>
                        <Item_0_2 type = "string">B</Item_0_2>
                    </ESU_Bl_0>
                    <ESU_Bl_1 type = "object">
                        <ID type = "number">2</ID>
                        <Item_1_1 type = "string">C</Item_1_1>
                        <Item_1_2 type = "string">D</Item_1_2>
                    </ESU_Bl_1>
                </a:item>
                <a:item xmlns:a = "item" item = "1" type = "object">
                    <ESU_Bl_0 type = "object">
                        <ID type = "number">3</ID>
                        <Item_0_1 type = "string">E</Item_0_1>
                        <Item_0_2 type = "string">F</Item_0_2>
                    </ESU_Bl_0>
                    <ESU_Bl_1 type = "object">
                        <ID type = "number">4</ID>
                        <Item_1_1 type = "string">G</Item_1_1>
                        <Item_1_2 type = "string">H</Item_1_2>
                    </ESU_Bl_1>
                </a:item>
            </ESU>
        </schData>
    </JSON>
</root>';

;WITH XMLNAMESPACES('item' AS a)
SELECT c.value('(ID/text())[1]', 'INT') AS ID
    , c.value('(Item_0_1/text())[1]', 'VARCHAR(20)') AS Item_0_1
    , c.value('(Item_0_2/text())[1]', 'VARCHAR(20)') AS Item_0_2
FROM @xml.nodes('/root/JSON/schData/ESU/a:item[@item = "0"]/ESU_Bl_0') AS t(c);

SQL №2

Метод XQuery .nodes() принимает только литеральный параметр. Но его легко параметризовать через sql:variable() или sql:column(). Пожалуйста, смотрите ниже.

DECLARE @Counter INT = 0;

;WITH XMLNAMESPACES('item' AS a)
SELECT c.value('(ID/text())[1]', 'INT') AS ID
    , c.value('(Item_0_1/text())[1]', 'VARCHAR(20)') AS Item_0_1
    , c.value('(Item_0_2/text())[1]', 'VARCHAR(20)') AS Item_0_2
FROM @xml.nodes('/root/JSON/schData/ESU/a:item[@item=sql:variable("@Counter")]/ESU_Bl_0') AS t(c);

Выход

ИДЕНТИФИКАТОР Товар_0_1 Товар_0_2 1 А Б

Привет @Yitzhak, я столкнулся с проблемой при динамизации вашего решения, обновил вопрос новой проблемой,

Bilal Siddiqui 26.12.2022 06:56

Я обновил ответ с помощью SQL # 2.

Yitzhak Khabinsky 26.12.2022 15:29
Ответ принят как подходящий

Итак, чтобы сделать его динамичным, вот что вы можете сделать с решением Ицхака:

;WITH XMLNAMESPACES('item' AS a)
SELECT c.value('(ID/text())[1]', 'INT') AS ID
    , c.value('(Item_0_1/text())[1]', 'VARCHAR(20)') AS Item_0_1
    , c.value('(Item_0_2/text())[1]', 'VARCHAR(20)') AS Item_0_2
FROM @xml.nodes('/root/JSON/schData/ESU/a:item[@item=sql:variable("@Counter")]/ESU_Bl_0') AS t(c);

Таким образом счетчик будет динамически вставлен.

Другие вопросы по теме