将xml文档拆分成块

本文关键字:拆分 文档 xml | 更新日期: 2023-09-27 17:47:46

我有一个大型xml文档,需要一次处理100条记录

这是在用c#编写的Windows服务中完成的。

结构如下:

<docket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="docket.xsd">
    <order>
        <Date>2008-10-13</Date>
        <orderNumber>050758023</orderNumber>
        <ParcelID/>
        <CustomerName>sddsf</CustomerName>
        <DeliveryName>dsfd</DeliveryName>
        <Address1>sdf</Address1>
        <Address2>sdfsdd</Address2>
        <Address3>sdfdsfdf</Address3>
        <Address4>dffddf</Address4>
        <PostCode/>
    </order>
    <order>
        <Date>2008-10-13</Date>
        <orderNumber>050758023</orderNumber>
        <ParcelID/>
        <CustomerName>sddsf</CustomerName>
        <DeliveryName>dsfd</DeliveryName>
        <Address1>sdf</Address1>
        <Address2>sdfsdd</Address2>
        <Address3>sdfdsfdf</Address3>
        <Address4>dffddf</Address4>
        <PostCode/>
    </order>
    .....
    .....
</docket>

一个案卷中可能有成千上万的订单。

我需要把它切成100个元素块

然而,100个订单中的每个订单仍然需要用父"docket"节点包装,并且具有相同的命名空间等

这可能吗?

将xml文档拆分成块

另一个天真的解决方案;这次是.NET 2.0。它应该让你知道如何去做你想要的事情。使用Xpath表达式而不是Linq-to-XML。在我的devbox上,在不到一秒钟的时间内将100个订单的摘要分为10个摘要。

 public List<XmlDocument> ChunkDocket(XmlDocument docket, int chunkSize)
    {
        List<XmlDocument> newDockets = new List<XmlDocument>();
        //            
        int orderCount = docket.SelectNodes("//docket/order").Count;
        int chunkStart = 0;
        XmlDocument newDocket = null;
        XmlElement root = null;
        XmlNodeList chunk = null;
        while (chunkStart < orderCount)
        {
            newDocket = new XmlDocument();
            root = newDocket.CreateElement("docket");
            newDocket.AppendChild(root);
            chunk = docket.SelectNodes(String.Format("//docket/order[position() > {0} and position() <= {1}]", chunkStart, chunkStart + chunkSize));
            chunkStart += chunkSize;
            XmlNode targetNode = null;
            foreach (XmlNode c in chunk)
            {
                targetNode = newDocket.ImportNode(c, true);
                root.AppendChild(targetNode);
            }
            newDockets.Add(newDocket);
        } 
        return newDockets;
    }

简洁、迭代,但有效[EDIT:仅在.NET 3.5中]

    public List<XDocument> ChunkDocket(XDocument docket, int chunkSize)
    {
        var newDockets = new List<XDocument>();
        var d = new XDocument(docket);
        var orders = d.Root.Elements("order");
        XDocument newDocket = null;
        do
        {
            newDocket = new XDocument(new XElement("docket"));
            var chunk = orders.Take(chunkSize);
            newDocket.Root.Add(chunk);
            chunk.Remove();
            newDockets.Add(newDocket);
        } while (orders.Any());
        return newDockets;
    }

如果一次处理100个订单是出于性能目的,例如打开一个大文件需要花费太多时间和资源,则可以使用XmlReader一次处理一个订单元素,而不会降低性能。

XmlReader reader = XmlReader.Create(@"c:'foo'Doket.xml")
while( reader.Read())
{
  if(reader.LocalName == "order")
  {
     // read each child element and its value from the reader.
     // or you can deserialize the order element by using a XmlSerializer and Order class
  }     
}