在 C# 中拆分 XML 文件并保留外部节点

Split XML file in C# and keep the outer nodes

我有一个 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 文件。使用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>

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

        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)
        {

        }