Преобразование XML в таблицу SQL Server с помощью C# (или любого другого метода)
У меня есть около 10 000 XML-файлов, где мне нужно преобразовать их в таблицу SQL.
Однако, вот проблемы, каждый XML-файл имеет некоторые вариации между собой, поэтому для меня почти невозможно указать имя элемента. Например:
//XML #1
<color>Blue</color>
<height>14.5</height>
<weight>150</weight>
<price>56.78</price>
//XML #2
<color>Red</color>
<distance>98.7</distance>
<height>15.5</height>
<price>56.78</price>
//XML #3: Some of the elements have no value
<color />
<height>14.5</height>
<price>78.11</price>
//XML #4: Elements has parent/child
<color>
<bodyColor>Blue</bodyColor>
<frontColor>Yellow</frontColor>
<backColor>White</backColor>
</color>
<height>14.5</height>
<weight>150</weight>
<price>56.78</price>
В приведенном выше примере я должен ожидать таблицу, созданную с именем columns: color, height, weight, price, distance (поскольку XML #2 имеет расстояние), bodyColor, frontColor, backColor.
Ожидаемый результат:
XML# color height weight price distance bodyColor frontColor backColor
1 Blue 14.5 150 56.78 NULL NULL NULL NULL
2 Red 15.5 NULL 56.78 98.7 NULL NULL NULL
3 NULL 14.5 NULL 78.11 NULL NULL NULL NULL
4 NULL 14.5 150 56.78 NULL Blue Yellow White
В этом случае NULL или пустое значение являются допустимый.
Это всего лишь примеры, в каждом XML-файле содержится не менее 500 элементов. Кроме того, хотя я упомянул здесь C#, если кто-нибудь может предложить лучший способ сделать это, пожалуйста, дайте мне знать.
2 ответов:
Одна возможность перебирать все xml-файлы и получать все уникальные теги может использовать LINQ2XML, класс HashSet и может выглядеть следующим образом:
Теперь у вас есть столбцы для основной таблицы SQL . С небольшим улучшением можно также отметить Родительский и подузлы. Это может помочь вам для нормализации.try { // add as many elements you want, they will appear only once! HashSet<String> uniqueTags = new HashSet<String>(); // recursive helper delegate Action<XElement> addSubElements = null; addSubElements = (xmlElement) => { // add the element name and uniqueTags.Add(xmlElement.Name.ToString()); // if the given element has some subelements foreach (var element in xmlElement.Elements()) { // add them too addSubElements(element); } }; // load all xml files var xmls = Directory.GetFiles("d:\\temp\\xml\\", "*.xml"); foreach (var xml in xmls) { var xmlDocument = XDocument.Load(xml); // and take their tags addSubElements(xmlDocument.Root); } // list tags foreach (var tag in uniqueTags) { Console.WriteLine(tag); } } catch (Exception exception) { Console.WriteLine(exception.Message); }
Это можно сделать в TSQL с помощью xQuery, промежуточной таблицы и динамического pivot.
Промежуточная таблица:
create table dbo.XMLStage ( ID uniqueidentifier not null, Name nvarchar(128) not null, Value nvarchar(max) not null, primary key (Name, ID) );
IDявляется уникальным для каждого файла,Nameсодержит имя узла иValueзначение узла.Хранимая процедура для заполнения промежуточной таблицы:
create procedure dbo.LoadXML @XML xml as declare @ID uniqueidentifier; set @ID = newid(); insert into dbo.XMLStage(ID, Name, Value) select @ID, T.X.value('local-name(.)', 'nvarchar(128)'), T.X.value('text()[1]', 'nvarchar(max)') from @XML.nodes('//*[text()]') as T(X);
//*[text()]даст вам все узлы, которые имеют текстовое значениеДинамический запрос для удаления данных из промежуточной таблицы:
declare @Cols nvarchar(max); declare @SQL nvarchar(max); set @Cols = ( select distinct ',' + quotename(X.Name) from dbo.XMLStage as X for xml path(''), type ).value('substring(text()[1], 2)', 'nvarchar(max)'); set @SQL = ' select '+@Cols+' from dbo.XMLStage pivot (max(Value) for Name in ('+@Cols+')) as P'; exec sp_executesql @SQL;Попробуйте это в этой скрипке SQL
Comments