LinqToXML优化查询

时间:2013-06-25 14:26:07

标签: c# lambda linq-to-xml

我该如何简化?

我有一个XML文件,如:

<Root>
    <Header />
    <Content />
    <Content />
    <Content />
    <!-- …. Lots of Contents -->
    <Footer />
</Root>

我需要拆分成较小的文件,以便每个文件都有一个'Header'和一个'Footer',然后X很多'Content'。 我当前的方法获取主文件的副本,删除所有内容,然后添加基于skip&amp;的所需内容。取。

我不喜欢它,因为我每次都会将原件复制到内存中,删除内容然后添加一些我刚删除的内容:

while (index < totalContents) {
    var newXDoc = new XDocument(xDoc);
    newXDoc.Descendants("Content").Remove();
    newXDoc.Root.Element("Header").AddAfterSelf(
        xDoc
            .Descendants("Content")
            .Skip(index)
            .Take(ordersPerFile)
    );

    xmlDocs.Add(XmlConverter.ToXmlDocument(newXDoc));

    index += ordersPerFile;
}

有更优雅的方式来执行此任务吗?

我正在寻找类似的东西:

while (index < totalContents) {
    var newXDoc = new XDocument(
        xDoc.Where(x => x.ContentElementsThatIWantForThisIteration...)
    );

    xmlDocs.Add(XmlConverter.ToXmlDocument(newXDoc));

    index += ordersPerFile;
}

由于

2 个答案:

答案 0 :(得分:4)

我会在中获取页眉和页脚 - 然后亲自使用MoreLINQ中的Batch方法:

var header = doc.Root.Element("Header");
var footer = doc.Root.Element("Footer");
var contents = doc.Root.Elements("Contents");

var newDocs = contents.Batch(ordersPerFile)
                      .Select(middle => new XDocument(
                                 new XElement("Root", header, middle, footer)))
                      .ToList();

如果您不想使用MoreLINQ,可以为所有内容创建List<XElement>,然后使用Skip / Take创建批次,或者显式获取它们按索引。 (Marcin的分组方法很好。)我建议使用MoreLINQ - 你可能会发现它在其他方面对你有用。

(免责声明:我启动了MoreLINQ项目,但从那时起它已经成长。虽然它可以通过Nuget package轻松安装。)

答案 1 :(得分:3)

您可以使用GroupBy来模拟分页,这样就可以将它们放在一个查询中。

var header = xDoc.Root.Element("Header");
var footer = xDoc.Root.Element("Footer");
var contents = xDoc.Root.Elements("Content")

var newXDocs = contents.Select((c, i) => new { c, i })
                       .GroupBy(x => x.i / ordersPerFile)
                       .Select(x => new XDocument(
                                       new XElement("Root",
                                           header,
                                           x.Select(y => y.c),
                                           footer)))
                       .ToList();

顺便说一句。使用Descendants使查询遍历整个XML树,因此最好使用Elements