разбить xml-документ на куски
У меня есть большой xml-документ, который должен быть обработан 100 записей одновременно
Это делается в рамках службы 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 заказов все еще должен быть обернут с родительским узлом" docket " и иметь то же пространство имен etc
Возможно ли это?
3 ответа:
Еще одно наивное решение; на этот раз для .NET 2.0. Это должно дать вам представление о том, как делать то, что вы хотите. Использует выражения Xpath вместо Linq to 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; }
Наивные, итерационный, но работает [редактировать: на .Объем только 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 } }