Извлечь информацию из неструктурированной XML-строки

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

<?xml version = "1.0" encoding = "utf-16"?>
<Advertentie>
  <Filter>
    <Woninglabels Enabled = "True" Priority = "1">
      <Woninglabel Id = "1" Type = "Huishoudgrootte" Enabled = "True" SeqNumber = "1" SortDirection = "DESC" Min = "0" Max = "99" Text = "" />
      <Woninglabel Id = "2" Type = "Leeftijd" Enabled = "True" SeqNumber = "2" SortDirection = "DESC" Min = "0" Max = "999" Text = "" />
    </Woninglabels>
  </Filter>
</Advertentie>

XML

Мне нужна информация о минимальных и максимальных значениях для каждого идентификатора Woninglabel (только что вставлены два, но их более 10). Проблема, с которой я сталкиваюсь, заключается в том, что вся информация находится между двумя "<" ">".

Я попробовал использовать метод .value(), но вскоре столкнулся с проблемой: вся информация находится между двумя этими "<" ">".

select TOP 100 ic,
CAST(ic AS XML).value('(<Advertentie><Filter><Woninglabels Enabled = "True" Priority = "1"><Woninglabel Id = "1" Type = "Huishoudgrootte" Enabled = "True" SeqNumber = "1" SortDirection = "DESC" Min = ")[1]','int(2)') AS Name
from adv

И получил эту ошибку: ошибка

Какие СУБД вы используете? (Приведенный выше запрос зависит от продукта.)

jarlh 05.09.2024 11:21

база данных sql на сервере Windows

Gerie 05.09.2024 11:36

SQL — это язык, поддерживаемый десятками различных продуктов, даже в Windows. Возможно вы имеете в виду MS SQL Server?

jarlh 05.09.2024 11:44

Да, это то, что я имею в виду

Gerie 05.09.2024 11:52

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

Dale K 05.09.2024 11:53

Затем исправьте свои теги, включив в них sql-server.

Dale K 05.09.2024 11:53

Вам нужно использовать функцию nodes, чтобы уничтожить каждую метку, а затем получить необходимые атрибуты. Здесь полезен метод value, доступ к атрибутам осуществляется с использованием синтаксиса @name. Почему бы не просмотреть документацию Microsoft XML, там это должно быть четко указано. Кстати, не знаю, почему вы думаете, что это неструктурированные данные.

siggemannen 05.09.2024 12:11
not structured XML вызывает некоторое противоречие, когда речь идет об XML, и ничего не объясняет. По определению XML имеет структуру. То, что вы опубликовали, очень хорошо структурировано: каждый элемент и атрибут имеет конкретное имя вместо ужасного name = "Price" value = "1,234" type = "good_luck_parsing_this". Вы можете использовать OPENXML для его анализа и извлечения атрибутов в виде столбцов, метод .query и XPATH для извлечения определенных частей. Проверьте примеры OPENXML в документации.
Panagiotis Kanavos 05.09.2024 12:21

Спасибо за помощь @siggemannen. Мне это показалось неструктурированным, но я также не очень знаком с получением данных из xml.

Gerie 05.09.2024 12:38

Я углублюсь в это @PanagiotisKanavos, большое спасибо. Также для объяснения структуры этого XML.

Gerie 05.09.2024 12:39
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
10
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это очень хорошо структурированный XML. Неструктурированный — это что-то вроде name = "Price" value = "1,234" type = "good_luck_parsing_this". Существует несколько способов запроса XML. Вы можете использовать .value для извлечения определенных значений на основе пути XPath..., вы можете использовать query для извлечения элементов в формате XML или использовать .nodes() для извлечения данных в виде набора строк, который может быть частью более крупного запроса.

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

select 
    a.value('./@Id','int') as Id,
    a.value('./@Type','nvarchar(20)') as Type,
    a.value('./@Enabled','bit') as Enabled,
    a.value('./@SeqNumber','int') as SeqNumber,
    a.value('./@Min','int') as Min,
    a.value('./@Max','int') as Max
from @xml.nodes('//Woninglabel') x(a)
---
Id  Type    Enabled SeqNumber   Min Max
1   Huishoudgrootte 1   1   0   99
2   Leeftijd    1   2   0   999

Или это, чтобы извлечь данные только одной метки:

select 
    a.value('./@Id','int') as Id,
    a.value('./@Type','nvarchar(20)') as Type,
    a.value('./@Enabled','bit') as Enabled,
    a.value('./@SeqNumber','int') as SeqNumber,
    a.value('./@Min','int') as Min,
    a.value('./@Max','int') as Max
from @xml.nodes('//Woninglabel') x(a)
where a.value('./@Id','int')=1
---
Id  Type    Enabled SeqNumber   Min Max
1   Huishoudgrootte 1   1   0   99

Если столбец таблицы имеет тип, отличный от XML, вы можете использовать CTE или подзапрос, чтобы сначала проанализировать текст в XML. Вы также можете поместить этот «измельчающий» код в представление, чтобы уменьшить сложность запроса.

declare @t table (OuterID bigint identity primary key,x nvarchar(max));
insert into @t values (@txt);


with parsed as (
 select *, cast(x as xml) xx1 from @t
)
select OuterID,
    a.value('./@Id','int') as Id,
    a.value('./@Type','nvarchar(20)') as Type,
    a.value('./@Enabled','bit') as Enabled,
    a.value('./@SeqNumber','int') as SeqNumber,
    a.value('./@Min','int') as Min,
    a.value('./@Max','int') as Max
from parsed 
cross apply xx1.nodes('//Woninglabel') x(a)
---
OuterID Id  Type    Enabled SeqNumber   Min Max
1   1   Huishoudgrootte 1   1   0   99
1   2   Leeftijd    1   2   0   999

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

with parsed as (
 select *, cast(x as xml) xx1 from @t
),
labels as (
    select OuterID,
        a.value('./@Id','int') as Id,
        a.value('./@Type','nvarchar(20)') as Type,
        a.value('./@Enabled','bit') as Enabled,
        a.value('./@SeqNumber','int') as SeqNumber,
        a.value('./@Min','int') as Min,
        a.value('./@Max','int') as Max
    from parsed 
    cross apply xx1.nodes('//Woninglabel') x(a)
)
select * from labels 
where SeqNumber=2

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