【问题标题】:Split XML file in C# and keep the outer nodes在 C# 中拆分 XML 文件并保留外部节点
【发布时间】:2026-02-13 20:30:01
【问题描述】:

我有一个如下所示的 XML 文件:

<root>
<elements>
    <element>
        <value1>a</value1>
        <value2>b</value2>
    </element>
    <element>
        <value1>c</value1>
        <value2>d</value2>
    </element>
    <element>
        <value1>e</value1>
        <value2>f</value2>
    </element>
    <element>
        <value1>g</value1>
        <value2>h</value2>
    </element>
</elements>
<return>0</return></root>

我想将它拆分成 x 个文件,如下所示: 例如

<root>
<elements>
    <element>
        <value1>a</value1>
        <value2>b</value2>
    </element>
    <element>
        <value1>c</value1>
        <value2>d</value2>
    </element>
</elements>
<return>0</return></root>

我使用的代码真的很丑,一点也不通用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace XMLSplit2
{
    class Program
    {
        static void Main(string[] args)
        {
            string filePath, file, outputFolder;
            XDocument xml;

            file = @"test.xml";
            outputFolder = @"C:\test\out\";
            filePath = @"C:\test\in\" + file;

            string _Header = @"<root><elements>";
            string _Footer = @"</elements><return>0</return></root>";
            int _BatchSize = 2;
            int i = 0;
            int j = 0;


            xml = XDocument.Load(filePath);
            XElement element = xml.Root.Elements().ElementAt(0);
            var xdoc = new XDocument(element);
            StringBuilder sb = new StringBuilder();


            string newXml = "";
            sb.Append(_Header);
            XElement last = xdoc.Root.Elements().Last();


            foreach (XElement singleElement in xdoc.Root.Elements())
            {
                i++;
                sb.Append(singleElement.ToString());
                if (i % _BatchSize == 0 || singleElement.Equals(last))
                {
                    j++;
                    sb.Append(_Footer);
                    newXml = sb.ToString();
                    System.IO.File.WriteAllText(outputFolder + j.ToString() + "_" + file, newXml);

                    sb.Clear();
                    sb.Append(_Header);
                }

            }

        }
    }
}

我想摆脱变量 _Header 和 _Footer。我该怎么做才能保持边界并用 x 元素节点填充它?还是说没有xslt就不行?

【问题讨论】:

  • 因此,您需要从原始 XML 文件中生成一个包含一半 &lt;element&gt; 的 XML 文件,其中仅包含值为 abcd 的元素,所有不等于efgh、...的元素?

标签: c# xml split


【解决方案1】:

通常应避免使用字符串连接构建 XML 文件。使用Linq-to-XML 就简单多了:

 // use this namespace
 using System.Xml.Linq;

 // Create 'footer' and 'header' elements
 XDocument xmlDoc = new XDocument();
 XElement xElm = new XElement("root",
                    new XElement("elements"),
                    new XElement("return", 0)                                    
                 );
 xmlDoc.Add(xElm);   

生产:

- <root>
  <elements /> 
  <return>0</return> 
  </root>

您现在可以轻松地从原始 XML 文件中添加所需的任何节点:

// Load XML file
XDocument doc = XDocument.Load(@"C:\mypath\mydoc.xml");
// Take the first two <element>s and add them to the new XML being produced
foreach (XElement elm in doc.Descendants("element").Take(2))
{
   xmlDoc.Root.Element("elements").Add(new XElement(elm));
}

获得所需的结果:

- <root>
- <elements>
   - <element>
        <value1>a</value1> 
        <value2>b</value2> 
     </element>
   - <element>
        <value1>c</value1> 
        <value2>d</value2> 
     </element>
  </elements>
  <return>0</return> 
  </root>

【讨论】:

    【解决方案2】:

    您可以使用以下解决方案来实现您的目标。

            try
            {
                var xDoc = new XmlDocument();
                string file = "input.xml";
                int batchSize = 2;
                if(File.Exists(file))
                {
                    xDoc.Load(file);
    
                    var elements = xDoc.DocumentElement.SelectNodes("/root/elements/element");
                    if(elements!=null && elements.Count>batchSize)
                    {
                        var elementsToRetain = elements.OfType<XmlNode>().Take(batchSize);
                        var elementsNode = xDoc.DocumentElement.SelectSingleNode("/root/elements");
                        elementsNode.RemoveAll();
    
                        foreach(var ele in elementsToRetain)
                        {
                            elementsNode.AppendChild(ele);
                        }
                    }
                    xDoc.Save("output.xml");
    
                }
            }
            catch (Exception e)
            {
    
            }
    

    【讨论】: