使用 C#(或任何其他方法)将 XML 转换为 SQL Server 表

Posted

技术标签:

【中文标题】使用 C#(或任何其他方法)将 XML 转换为 SQL Server 表【英文标题】:Converting XML to SQL Server Table using C# (or any other method) 【发布时间】:2014-06-10 04:41:48 【问题描述】:

我有大约 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#,如果有人可以提出更好的方法,请告诉我。

【问题讨论】:

获取文件以遵循某个 Xml 架构定义。标签可以为空或 NULL。存在标签很重要。然后使用该文件会更容易。 @abhi XML 模式定义是什么意思? (对不起,我对 XML 很陌生) 一种可能的解决方案是遍历每个 XML 文件并提取所有唯一字段并在数据库中创建一个包含所有提取的唯一字段的表。这样您就可以知道您拥有哪些字段,以便您以后可以考虑对表格进行规范化。 @Hituptony 我正要发帖same link。 您可以获得一个包含所有可能标签的示例文件。然后 Visual Studio 将为您创建 XSD。市场上还有其他工具在这个游戏中表现更好。想到 Altova XML SPY 和 Liquid。 2011 年,我正在从事一项非常相似的活动。 【参考方案1】:

遍历所有 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);

现在您有了 basic SQL 表的 。只需稍加增强,您还可以标记父节点和子节点。这可以帮助您进行规范化。

【讨论】:

您给了我一个良好的开端,但是,我刚刚发现了 XML 中的更多问题。我遇到的问题是,在一个 XML 中,它的元素如下:&lt;color&gt;Red&lt;/color&gt; &lt;color&gt;Blue&lt;/color&gt; &lt;color&gt;Green&lt;/color&gt; 这些是 3 种不同的颜色,但由于独特的过滤器,它只返回 color 1 次而不是 3 次。 这就是为什么您可能还需要考虑 nesting 级别,以便您也可以添加具有相同名称的 subelements。无论如何,您都需要分析整个输入数据。例如,可以将嵌套颜色标签重命名为 bodyColorfrontColor 等等或更合适的名称,例如 blueComponent 还是谢谢你,至少你的代码给了我一个先机,我会修改它以适应我需要的条件 很高兴这个答案有帮助。【参考方案2】:

您可以在 TSQL 中使用 xQuery、临时表和动态数据透视表来执行此操作。

暂存表:

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 Fiddle试试吧

【讨论】:

以上是关于使用 C#(或任何其他方法)将 XML 转换为 SQL Server 表的主要内容,如果未能解决你的问题,请参考以下文章

将带有命名空间和属性的 XML 转换为 C# 模型类

将 HDF5 文件转换为其他格式

使用 C# 将 HTML 控件(Div 或表格)转换为图像

将 XML 转换为 C# 类的工具 [重复]

正则表达式 - 将 HTML 转换为有效的 XML 标记 [重复]

我正在使用 C# 将 XML 文件转换为 CSV。我尝试了不同的方法,但无法弄清楚如何访问键名/值对