2008-10-30 1 views
2

У меня есть большой XML-документ, который должен быть обработаны 100 записей, в то времяраскол XML документа на куски

Это делается в рамках службы Windows, написанной в C#.

структура выглядит следующим образом:

<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 заказов по-прежнему должны быть обернуты с родителем «накладная» узла и имеют то же пространство имен и т.д.

это возможно?

ответ

5

Другой наивным решение; на этот раз для .NET 2.0. Это должно дать вам представление о том, как идти по тому, что вы хотите. Использует выражения Xpath вместо Linq для XML. Куски 100-разрядной доски в 10 гнезд в секунду на моем devbox.

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; 
    } 
1

Наивные, итеративный, но работает [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; 
    } 
+0

Я знаю его ужасно неэффективно. – 2008-10-30 06:26:57

0

Если причина для обработки 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 
    }  
}