我有大约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#,如果有人能提出更好的方法,请告诉我。
答案 0 :(得分:2)
迭代所有xml文件并获取所有唯一标记的一种可能性可以使用LINQ2XML HashSet class,看起来像这样:
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);
}
现在您拥有基本 SQL表的列。几乎没有增强,您还可以标记父节点和子节点。这可以帮助您进行规范化。
答案 1 :(得分:1)
您可以使用xQuery,临时表和动态数据透视表在TSQL中执行此操作。
临时表:
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;
中试用