1

我怎样才能简化这个?

我有一个 XML 文件,例如:

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

我需要拆分成更小的文件,以便每个文件都有一个“页眉”和一个“页脚”,然后是 X 多个“内容”。我当前的方法获取主文件的副本,删除所有内容,然后根据 skip & take 添加所需的内容。

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

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

谢谢

4

2 回答 2

4

好吧,我会一次获取页眉和页脚- 然后亲自使用Batch来自MoreLINQ的方法:

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 包轻松安装。)

于 2013-06-25T14:33:55.210 回答
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();

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

于 2013-06-25T14:36:30.283 回答