我需要获取一个XML文件,并从输入文件的重复节点创建多个输出xml文件。源文件"AnimalBatch.xml“如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Animal id="1001">
<Quantity>One</Quantity>
<Adjective>Red</Adjective>
<Name>Rooster</Name>
</Animal>
<Animal id="1002">
<Quantity>Two</Quantity>
<Adjective>Stubborn</Adjective>
<Name>Donkeys</Name>
</Animal>
<Animal id="1003">
<Quantity>Three</Quantity>
<Color>Blind</Color>
<Name>Mice</Name>
</Animal>
</Animals>
该程序需要拆分重复的“动物”并生成三个名为Animal_1001.xml、Animal_1002.xml和Animal_1003.xml的文件
每个输出文件应该只包含它们各自的元素(这将是根)。AnimalsBatch.xml的id属性将提供Animal_xxxx.xml文件名的序列号。id属性不需要在输出文件中。
Animal_1001.xml:
<?xml version="1.0" encoding="utf-8"?>
<Animal>
<Quantity>One</Quantity>
<Adjective>Red</Adjective>
<Name>Rooster</Name>
</Animal>
Animal_1002.xml
<?xml version="1.0" encoding="utf-8"?>
<Animal>
<Quantity>Two</Quantity>
<Adjective>Stubborn</Adjective>
<Name>Donkeys</Name>
</Animal>
Animal_1003.xml>
<?xml version="1.0" encoding="utf-8"?>
<Animal>
<Quantity>Three</Quantity>
<Adjective>Blind</Adjective>
<Name>Mice</Name>
</Animal>
我想用XmlDocument来实现这一点,因为它需要能够在.Net 2.0上运行。
我的程序是这样的:
    static void Main(string[] args)
    {
        string strFileName;    
        string strSeq;                    
        XmlDocument doc = new XmlDocument(); 
        doc.Load("D:\\Rick\\Computer\\XML\\AnimalBatch.xml");
        XmlNodeList nl = doc.DocumentElement.SelectNodes("Animal");
        foreach (XmlNode n in nl)
        {
            strSeq = n.Attributes["id"].Value;
            XmlDocument outdoc = new XmlDocument();
            XmlNode rootnode = outdoc.CreateNode("element", "Animal", "");
            outdoc.AppendChild(rootnode); // Put the wrapper element into outdoc
            outdoc.ImportNode(n, true);   // place the node n into outdoc
            outdoc.AppendChild(n);        // This statement errors:
            // "The node to be inserted is from a different document context."
            strFileName = "Animal_" + strSeq + ".xml";
            outdoc.Save(Console.Out);
            Console.WriteLine();
        }
        Console.WriteLine("END OF PROGRAM:  Press <ENTER>");
        Console.ReadLine();
    }我想我有两个问题。
( A)在将节点n上的ImportNode执行到outdoc之后,我调用outdoc.AppendChild(n),它抱怨道:“要插入的节点来自不同的文档上下文。”我不知道这是否是ForEach循环中引用节点n的作用域问题,或者我不知怎么没有正确地使用ImportNode()或AppendChild。ImportNode()上的第二个参数设置为true,因为我希望动物的子元素(3个字段任意命名数量、形容词和名称)在目标文件中结束。
( B)第二个问题是把动物元素弄到外面去。我得到了“但我需要”,这样我就可以在其中放置节点n。我想我的问题是我是怎么做的:outdoc.AppendChild(根节点);
为了显示xml,我做的是: outdoc.Save(Console.Out);我确实有将()保存到输出文件中的代码--只要我能够正确地组装出outdoc,它就能工作。
在:Split XML in Multiple XML files有一个类似的问题,但我还不明白解决方案代码。我认为我非常接近这个方法,并且会感谢你能提供的任何帮助。
我将使用XmlReader完成同样的任务,因为我需要能够处理大型输入文件,而且我知道XmlDocument会读取全部内容,并可能导致内存问题。
发布于 2012-08-11 07:08:14
这是一种简单的方法,看起来就是你想要的
public void test_xml_split()
{
    XmlDocument doc = new XmlDocument();
    doc.Load("C:\\animals.xml");
    XmlDocument newXmlDoc = null;
    foreach (XmlNode animalNode in doc.SelectNodes("//Animals/Animal"))
    {
        newXmlDoc = new XmlDocument();
        var targetNode = newXmlDoc.ImportNode(animalNode, true);
        newXmlDoc.AppendChild(targetNode);
        newXmlDoc.Save(Console.Out);
        Console.WriteLine();
    }
}发布于 2012-08-12 02:11:48
这种方法在不使用"var塔吉特节点“语句的情况下似乎有效。它从outdoc的“targetNode”元素在ForEach循环中创建一个名为targetNode的ForEach对象。我认为我的原始代码中的主要问题是:( A)我不正确地获得了nodelist nl。我不能“导入”节点n,我想是因为它是专门与doc关联的。它必须作为自己的节点创建。
先前提出的解决方案的问题是使用"var“关键字。我的程序必须假设2.0,而这是随v3.0而来的。我喜欢罗杰斯的解决方案,因为它很简洁。对我来说-我想做每一件事作为一个单独的陈述。
    static void SplitXMLDocument() 
    {
        string strFileName;
        string strSeq;
        XmlDocument doc = new XmlDocument();             // The input file
        doc.Load("D:\\Rick\\Computer\\XML\\AnimalBatch.xml");
        XmlNodeList nl = doc.DocumentElement.SelectNodes("//Animals/Animal");
        foreach (XmlNode n in nl)
        {
            strSeq = n.Attributes["id"].Value;           // Animal nodes have an id attribute
            XmlDocument outdoc = new XmlDocument();      // Create the outdoc xml document
            XmlNode targetNode = outdoc.CreateElement("Animal"); // Create a separate node to hold the Animal element
            targetNode = outdoc.ImportNode(n, true);     // Bring over that Animal
            targetNode.Attributes.RemoveAll();           // Remove the id attribute in <Animal id="1001">
            outdoc.ImportNode(targetNode, true);         // place the node n into outdoc
            outdoc.AppendChild(targetNode);              // AppendChild to make it stick
            strFileName = "Animal_" + strSeq + ".xml";                
            outdoc.Save(Console.Out); Console.WriteLine();
            outdoc.Save("D:\\Rick\\Computer\\XML\\" + strFileName);
            Console.WriteLine();
        }
    }https://stackoverflow.com/questions/11912109
复制相似问题