【问题标题】:Parsing a large XML file to multiple output xmls, using XmlReader - getting every other element使用 XmlReader 将大型 XML 文件解析为多个输出 xml - 获取所有其他元素
【发布时间】:2012-08-30 00:34:58
【问题描述】:

我需要获取一个非常大的 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><Adjective>Blind</Adjective><Name>Mice</Name></Animal><Animal id="1004"><Quantity>Four</Quantity><Adjective>Purple</Adjective><Name>Horses</Name></Animal><Animal id="1005"><Quantity>Five</Quantity><Adjective>Long</Adjective><Name>Centipedes</Name></Animal><Animal id="1006"><Quantity>Six</Quantity><Adjective>Dark</Adjective><Name>Owls</Name></Animal></Animals>

程序需要对重复的“Animal”进行拆分,生成适当数量的文件,命名为:Animal_1001.xml、Animal_1002.xml、Animal_1003.xml等


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>

下面的代码有效,但前提是输入文件在 <Animal id="xxxx"> 元素之后有 CR/LF。如果它没有“空白”(我没有,也不能那样得到),我会得到其他所有的(奇数动物)

    static void SplitXMLReader()
    {
        string strFileName;
        string strSeq = "";

        XmlReader doc = XmlReader.Create("C:\\AnimalBatch.xml");

        while (doc.Read())
        {
            if ( doc.Name == "Animal"  && doc.NodeType == XmlNodeType.Element )
            {
                strSeq = doc.GetAttribute("id"); 

                XmlDocument outdoc = new XmlDocument();
                XmlDeclaration xmlDeclaration = outdoc.CreateXmlDeclaration("1.0", "utf-8", null);                     
                XmlElement rootNode = outdoc.CreateElement(doc.Name);

                rootNode.InnerXml = doc.ReadInnerXml();  
                // This seems to be advancing the cursor in doc too far.

                outdoc.InsertBefore(xmlDeclaration, outdoc.DocumentElement);
                outdoc.AppendChild(rootNode);

                strFileName = "Animal_" + strSeq + ".xml";
                outdoc.Save("C:\\" + strFileName);                    
            }
        }
    }

我的理解是,XML 中的“空白”或格式对 XmlReader 没有影响——但我已经尝试过这两种方式,在 <Animal id="xxxx"> 之后有和没有 CR/LF,并且可以确认存在差异。如果它有 CR/LF(甚至可能只是一个空格,我将在接下来尝试) - 它会完全处理每个 <Animal> 节点,并保存在来自 id 属性的正确文件名下。

有人可以告诉我这里发生了什么 - 以及可能的解决方法吗?

【问题讨论】:

  • 这不是你所有其他问题的重复吗?
  • 跟进?这更像是让 SO 人一步一步地写 OP 的工作,而他除了问问题之外没有表现出任何真正的努力
  • 我发现空格很重要。我将示例扩展为六个元素,以显示我认为问题的模式——输入文件上的光标刚好位于下一个元素的开头。我之前的问题在每个元素之后都有 CR/LF。事实证明我不会拥有这些——这是我无法控制的限制。也许我必须在这种情况下使用 XmlTextReader?
  • 没有真正的努力?!我自己已经为此工作了一段时间 - 并且正在尝试以几种不同的方式自己做。只有当我发现约翰关于“空白无关紧要”的评论不正确时——我才寻求帮助——并表明事实并非如此。
  • 另外 - 之前的问题具体是:如何使用 XmlDocument 将其拆分,如何使用 XmlTextReader 进行操作,以及如何使用 XmlReader 进行操作。我承认我弄错了输入文件的样子——但它确实有所作为。我要做的下一个是如何使用 XDocument 执行此操作。这将涵盖四种主要不同的皮肤相同基本方法 - 但我敢肯定,这是很常见的问题。

标签: c# xml split large-files xmlreader


【解决方案1】:

是的,当使用doc.readInnerXml() 时,空格很重要。

From the documentation of the function。这将返回一个字符串。所以当然空白很重要。如果您希望内部文本作为 xmlNode,您应该使用 something like this

【讨论】:

【解决方案2】:

感谢使用 ReadSubTree() 方法的指导:

此代码适用于没有换行符的 XML 输入文件:

    static void SplitXMLReaderSubTree()
    {
        string strFileName;
        string strSeq = "";
        XmlReader doc = XmlReader.Create("C:\\AnimalBatch.xml");

        while (!doc.EOF)
        {
            if ( doc.Name == "Animal"  && doc.NodeType == XmlNodeType.Element )
            {
                strSeq = doc.GetAttribute("id");
                XmlReader inner = doc.ReadSubtree();
                inner.Read();
                XmlDocument outdoc = new XmlDocument();
                XmlDeclaration xmlDeclaration = outdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                XmlElement myElement;
                myElement = outdoc.CreateElement(doc.Name);
                myElement.InnerXml = inner.ReadInnerXml();
                inner.Close();
                myElement.Attributes.RemoveAll();
                outdoc.InsertBefore(xmlDeclaration, outdoc.DocumentElement);
                outdoc.ImportNode(myElement, true);
                outdoc.AppendChild(myElement);
                strFileName = "Animal_" + strSeq + ".xml";
                outdoc.Save("C:\\" + strFileName);                    
            }
            else
            {
                doc.Read();
            }
        }

【讨论】:

    猜你喜欢
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多