C# 获取重复 XML 标签到 DataTable
C# Get repeating XML tags into DataTable
我有一个 XML 文件,我试图在 C# 程序中解析并保存到数据库中。对于此文件中的大多数元素,我已经能够使用 SqlBulkCopy,因为这些元素排列得很好,子标签的唯一名称或根节点上的属性。但是,我有一个元素的子元素带有重复的标签名称(只是“标签”),但使用属性名称来描述它是什么。我无法使用 SqlBulkCopy 保存它,我更喜欢使用 SqlBulkCopy,因为这个文件可以大到 500MB,而 SqlBulkCopy class 更快。我尝试了下面的代码,但通过调试可以看到 ds.Tables 集合正在分离主机属性和标签。我猜这就是 ReadXml 方法的工作原理。将这些标记放入一个数据表对象中的最简单方法是什么,该数据表对象将各个属性作为列,以便我可以使用 SqlBulkCopy?
当前 C# 代码
DataSet ds = new DataSet();
ds.ReadXml(file.InputStream);
DataTable hostItems = ds.Tables["host"];
conn.Open();
using (SqlBulkCopy sb = new SqlBulkCopy(conn))
{
sb.DestinationTableName = "HOSTS";
sb.ColumnMappings.Add("host-ip", "HOST_IP");
sb.ColumnMappings.Add("host-name", "NAME");
sb.ColumnMappings.Add("system-type", "SSH_FINGERPRINT");
sb.ColumnMappings.Add("os", "OS");
sb.WriteToServer(hostItems);
}
XML 文件
<host>
<tag name="host-ip">192.168.200.8</tag>
<tag name="host-name">someserver.mydomain.com</tag>
<tag name="system-type">webserver</tag>
<tag name="os">WindowsServer2019</tag>
</host>
...
<host>
<tag name="host-ip">192.168.200.9</tag>
<tag name="host-name">someserver2.mydomain.com</tag>
<tag name="system-type">webserver</tag>
<tag name="os">WindowsServer2019</tag>
<tag name="attributeFirstOneDidntHave">Some nonsense</tag>
</host>
编辑
我没有提到并非所有主机都具有相同数量的标签。我已经更新了 XML 示例来说明这一点。
对于巨大的 xml 文件,您需要使用 XmlReader,否则,您将遇到内存不足的错误。下面的代码使用了 xmlreader 和 xml linq
的组合
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
XmlReader reader = XmlReader.Create(FILENAME);
long count = 0;
while (!reader.EOF)
{
if (reader.Name != "host")
{
reader.ReadToFollowing("host");
}
if (!reader.EOF)
{
XElement host = (XElement)XElement.ReadFrom(reader);
if (++count == 1)
{
foreach (XElement tag in host.Elements("tag"))
{
dt.Columns.Add((string)tag.Attribute("name"),typeof(string));
}
}
DataRow row = dt.Rows.Add();
foreach (XElement tag in host.Elements("tag"))
{
row[(string)tag.Attribute("name")] = (string)tag;
}
}
}
}
}
}
我有一个 XML 文件,我试图在 C# 程序中解析并保存到数据库中。对于此文件中的大多数元素,我已经能够使用 SqlBulkCopy,因为这些元素排列得很好,子标签的唯一名称或根节点上的属性。但是,我有一个元素的子元素带有重复的标签名称(只是“标签”),但使用属性名称来描述它是什么。我无法使用 SqlBulkCopy 保存它,我更喜欢使用 SqlBulkCopy,因为这个文件可以大到 500MB,而 SqlBulkCopy class 更快。我尝试了下面的代码,但通过调试可以看到 ds.Tables 集合正在分离主机属性和标签。我猜这就是 ReadXml 方法的工作原理。将这些标记放入一个数据表对象中的最简单方法是什么,该数据表对象将各个属性作为列,以便我可以使用 SqlBulkCopy?
当前 C# 代码
DataSet ds = new DataSet();
ds.ReadXml(file.InputStream);
DataTable hostItems = ds.Tables["host"];
conn.Open();
using (SqlBulkCopy sb = new SqlBulkCopy(conn))
{
sb.DestinationTableName = "HOSTS";
sb.ColumnMappings.Add("host-ip", "HOST_IP");
sb.ColumnMappings.Add("host-name", "NAME");
sb.ColumnMappings.Add("system-type", "SSH_FINGERPRINT");
sb.ColumnMappings.Add("os", "OS");
sb.WriteToServer(hostItems);
}
XML 文件
<host>
<tag name="host-ip">192.168.200.8</tag>
<tag name="host-name">someserver.mydomain.com</tag>
<tag name="system-type">webserver</tag>
<tag name="os">WindowsServer2019</tag>
</host>
...
<host>
<tag name="host-ip">192.168.200.9</tag>
<tag name="host-name">someserver2.mydomain.com</tag>
<tag name="system-type">webserver</tag>
<tag name="os">WindowsServer2019</tag>
<tag name="attributeFirstOneDidntHave">Some nonsense</tag>
</host>
编辑
我没有提到并非所有主机都具有相同数量的标签。我已经更新了 XML 示例来说明这一点。
对于巨大的 xml 文件,您需要使用 XmlReader,否则,您将遇到内存不足的错误。下面的代码使用了 xmlreader 和 xml linq
的组合using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
XmlReader reader = XmlReader.Create(FILENAME);
long count = 0;
while (!reader.EOF)
{
if (reader.Name != "host")
{
reader.ReadToFollowing("host");
}
if (!reader.EOF)
{
XElement host = (XElement)XElement.ReadFrom(reader);
if (++count == 1)
{
foreach (XElement tag in host.Elements("tag"))
{
dt.Columns.Add((string)tag.Attribute("name"),typeof(string));
}
}
DataRow row = dt.Rows.Add();
foreach (XElement tag in host.Elements("tag"))
{
row[(string)tag.Attribute("name")] = (string)tag;
}
}
}
}
}
}