【问题标题】:What is the fastest way to combine two xml files into one将两个xml文件合并为一个的最快方法是什么
【发布时间】:2010-11-02 05:27:33
【问题描述】:

如果我有两个 xml1 和 xml2 字符串,它们都以相同的格式表示 xml。将这些结合在一起的最快方法是什么?格式不重要,但我只想知道如何摆脱或?

xml1:

<?xml version="1.0" encoding="utf-8"?>
<AllNodes>
   <NodeA>
      <NodeB>test1</NodeB>
      <NodeB>test2</NodeB>
   </NodeA>
</AllNodes>

xm2:

<?xml version="1.0" encoding="utf-8"?>
<AllNodes>
   <NodeA>
      <NodeB>test6</NodeB>
      <NodeB>test7</NodeB>
   </NodeA>
   <NodeA>
      <NodeB>test99</NodeB>
      <NodeB>test23</NodeB>
   </NodeA>
</AllNodes>

并且有这样的东西:

<?xml version="1.0" encoding="utf-8"?>
    <AllNodes>
          <NodeA>
              <NodeB>test1</NodeB>
              <NodeB>test2</NodeB>
          </NodeA>
         <NodeA>
              <NodeB>test6</NodeB>
              <NodeB>test7</NodeB>
           </NodeA>
           <NodeA>
              <NodeB>test99</NodeB>
              <NodeB>test23</NodeB>
           </NodeA>
    </AllNodes>

【问题讨论】:

标签: c# xml


【解决方案1】:

如果我这样做(使用 C#),我将创建一个可以反序列化此 XML 的类(您可以使用 xsd.exe 来执行此操作),然后遍历对象中代表第一个的所有节点一段 XML 并将它们“添加”到表示第二个 XML 的对象的 AllNodes 属性中。

然后将第二个类序列化回 XML,它应该看起来像您的第三个示例。

【讨论】:

    【解决方案2】:

    您有两个基本选择:

    1. 解析xml,组合数据结构,序列化回xml。

    2. 如果您知道结构,请使用一些基本的字符串操作来破解它。例如,在上面的示例中,您可以将两个 xml 块中的 allnodes 的内部放入单个 allnodes 块中并完成。

    【讨论】:

      【解决方案3】:

      XSLT 转换可以做到这一点:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:param name="pXml1" select="''" />
        <xsl:param name="pXml2" select="''" />
        <xsl:param name="pRoot" select="'root'" />
      
        <xsl:template match="/">
          <xsl:variable name="vXml1" select="document($pXml1)" />
          <xsl:variable name="vXml2" select="document($pXml2)" />
      
          <xsl:element name="{$pRoot}">
            <xsl:copy-of select="$vXml1/*/*" />
            <xsl:copy-of select="$vXml2/*/*" />
          </xsl:element>
        </xsl:template>
      
      </xsl:stylesheet>
      

      将文件名作为参数传入,以及新根元素的名称。

      适用于任何 XML 文档,例如一个空的。

      【讨论】:

      • 非常感谢。您的解决方案看起来不错,但您知道如何将该架构应用到 xml 文档吗?
      • 例如,stackoverflow.com/questions/529374/… 接受的答案显示了如何在 .NET 中执行此操作
      • 另一方面 - 如果您对 XSLT 毫无了解,那么它可能不是您的理想解决方案。而且我不知道与此线程中建议的其他方式相比,它的表现如何。
      【解决方案4】:

      如果你能保证这种格式,你可以通过字符串操作来组合它们:

      • 读取第一个文件,保留“”之前的所有内容
      • 读取第二个文件,删除“”之前的部分
      • 组合这些字符串。

      这应该是最快的方式,因为不需要解析。

      const string RelevantTag = "AllNodes";
      
      string xml1 = File.ReadAllText(xmlFile1);
      xml1 = xml1.Substring(0, xml.LastIndexOf("</" + RelevantTag + ">"));
      
      string xml2 = File.ReadAllText(xmlFile2);
      xml2 = xml2.Substring(xml.IndexOf("<" + RelevantTag + ">") + "<" + RelevantTag + ">".Length, xml1.Length);
      
      File.WriteAllText(xmlFileCombined, xm1 + xml2);
      

      也就是说我总是更喜欢安全的方式而不是快速的方式。

      【讨论】:

        【解决方案5】:

        最简单的方法是使用 LINQ to XML。您可以根据需要使用UnionConcat

        var xml1 = XDocument.Load("file1.xml");
        var xml2 = XDocument.Load("file2.xml");
        
        //Combine and remove duplicates
        var combinedUnique = xml1.Descendants("AllNodes")
                                  .Union(xml2.Descendants("AllNodes"));
        
        //Combine and keep duplicates
        var combinedWithDups = xml1.Descendants("AllNodes")
                                   .Concat(xml2.Descendants("AllNodes"));
        

        【讨论】:

        • 好吧,问题是我有两个字符串而不是两个 xml 文件。这两个字符串代表从另一个站发送的 xml 元素。有没有办法将我的字符串转换为 XElement 或类似的东西?所以我可以遍历它的元素?
        • 要将字符串转换为 XElement,可以使用 XElement.Parse(yourstring)
        • 您也可以使用 XDocument.Parse(yourstring) 将字符串转换为 XDocument
        • Jose Basilio 的回答非常好但不完整,它将创建一个带有 2 个“AllNodes”元素的 XElement IEnumerator。更准确的答案是(如果重复不是问题):xml1.Descendants("NodeA").LastOrDefault().AddAfterSelf(xml2.Descendants("NodeA")); xml1.Save();
        • @Vlax 这是一个完美的完成,你能告诉我如何将此文件另存为新文件吗?就像如果xml2被xml1替换并且我需要将结果另存为xml3,这可能吗?
        【解决方案6】:

        既然您要求最快

        如果(且仅当)xml 结构始终一致:(这是伪代码)

        string xml1 = //get xml1 somehow
        string xml2 = //get xml2 somehow
        xml1 = replace(xml1, "<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
        xml1 = replace(xml1, "<allnodes>", "");
        xml1 = replace(xml1, "</allnodes>", "");
        xml2 = replace(xml2, "<allnodes>", "<allnodes>\n" + xml1);
        

        这是一个巨大的 hack,但速度很快。当您的同事找到它时,希望在 TheDailyWTF 上看到它。

        【讨论】:

          【解决方案7】:

          如果你想使用 XmlDocument,试试这个

           var lNode = lDoc1.ImportNode(lDoc2.DocumentElement.FirstChild, true);
           lDoc1.DocumentElement.AppendChild(lNode);
          

          【讨论】:

            【解决方案8】:
            var doc= XDocument.Load("file1.xml");
            var doc1= XDocument.Load("file2.xml");
            doc.Root.Add(doc2.Root.Elements());
            

            【讨论】:

            • 最简单也是最好的方法。
            【解决方案9】:

            这是合并 xml 文件最快、最干净的方法。

            XElement xFileRoot = XElement.Load(file1.xml);
            XElement xFileChild = XElement.Load(file2.xml);
            xFileRoot.Add(xFileChild);
            xFileRoot.Save(file1.xml);
            

            【讨论】:

            • 这会保留还是删除重复项?
            【解决方案10】:

            对我来说最好的解决方案,基于 Jose Basilio 的回答,稍作修改,

            var combinedUnique = xml1.Descendants()
                .Union(xml2.Descendants());
            combinedUnique.First().Save(#fullName)
            

            【讨论】:

            • 感谢@user3510339 提供代码,但它仅保存第一个 XML 文件的内容。 TIA
            【解决方案11】:

            在我的情况下主要解决方案效果不佳,不同之处在于,当我获取一个元素并尝试与我得到 OutOfMemory 的第一个元素合并时,我有一个包含数千个文件的列表例外,我添加了一个空模板和空行(本例中为NodeA),以解决内存的奇怪问题并顺利运行。

            我将文档保存在其他进程中

            XDocument xmlDocTemplate = GetXMLTemplate(); -- create an empty document with the same root and empty row element (NodeA), everything will be merge here.
            List<XElement> lstxElements = GetMyBunchOfXML();
            
            foreach (var xmlElement lstxElements)
            {
                xmlDocTemplate
                    .Root
                    .Descendants("NodeA")
                    .LastOrDefault()
                    .AddAfterSelf(xmlElement.Descendants("NodeA"));
            }
            

            【讨论】:

              猜你喜欢
              • 2017-10-27
              • 2016-08-11
              • 2010-12-23
              • 2013-08-11
              • 2013-06-07
              • 1970-01-01
              • 2012-04-24
              • 1970-01-01
              相关资源
              最近更新 更多