C# 将两个xml文件合并为一个xml文件的最快方法是什么

C# 将两个xml文件合并为一个xml文件的最快方法是什么,c#,xml,C#,Xml,如果我有两个字符串xml1和xml2,它们都以相同的格式表示xml。把这些结合在一起最快的方法是什么?格式并不重要,但我只想知道如何摆脱或删除 xml1: <?xml version="1.0" encoding="utf-8"?> <AllNodes> <NodeA> <NodeB>test1</NodeB> <NodeB>test2</NodeB> </NodeA&g

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

xml1:

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

测试1
测试2
xm2:


测试6
测试7
测试99
测试23
有这样的东西:

<?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>

测试1
测试2
测试6
测试7
测试99
测试23
如果我正在这样做(使用C#),我会创建一个类,我可以将这个XML反序列化到该类(可以使用xsd.exe来执行此操作),然后循环遍历对象中表示第一段XML的所有节点,并将它们“添加”到表示第二段XML的对象的AllNodes属性中


然后将第二个类序列化回XML,它应该与您的第三个示例类似。

您有两个基本选项:

  • 解析xml,组合数据结构,序列化回xml

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


  • 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文档,例如空文档。

    如果可以保证此格式,则可以通过执行字符串操作将其组合:

    • 读取第一个文件,在“”之前保留所有内容
    • 读取第二个文件,删除零件直至“”
    • 把这些弦组合起来
    这应该是最快的方法,因为不需要解析

    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);
    
    const string relevantag=“AllNodes”;
    字符串xml1=File.ReadAllText(xmlFile1);
    xml1=xml1.Substring(0,xml.LastIndexOf(“”);
    字符串xml2=File.ReadAllText(xmlFile2);
    xml2=xml2.Substring(xml.IndexOf(“”+“”)长度,xml1.Length);
    writealText(xmlFileCombined,xm1+xml2);
    

    也就是说,与快速方法相比,我更喜欢安全方法。

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

    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结构始终一致:(这是伪代码)

    string xml1=//以某种方式获取xml1
    字符串xml2=//以某种方式获取xml2
    xml1=替换(xml1,“,”);
    xml1=替换(xml1,“,”);
    xml1=替换(xml1,“,”);
    xml2=替换(xml2,“,“\n”+xml1);
    

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

    如果您想使用XML文档,请尝试以下方法

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

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

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

    我的最佳解决方案,基于Jose Basilio的回答,稍加修改

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

    在我的例子中,主要的解决方案没有很好地工作,不同的是,当我获取一个元素并尝试与从内存中获取的第一个元素合并时,我有一个包含数千个文件的列表。例外,我添加了一个空模板,其中包含一个空行(本例中为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"));
    }
    
    XDocument xmlDocTemplate=GetXMLTemplate();--创建一个具有相同根元素和空行元素(NodeA)的空文档,所有内容都将在此处合并。
    List lstxElements=GetMyBunchOfXML();
    foreach(var xmlElement lstxElements)
    {
    xmlDocTemplate
    .根
    .后代(“NodeA”)
    .LastOrDefault()
    .AddAfterSelf(xmlement.substands(“NodeA”);
    }
    
    非常感谢您。您的解决方案看起来不错,但您知道我如何将该模式应用于xml文档吗?例如,的公认答案显示了如何在.NET中实现这一点。另一方面,如果您对XSLT一无所知,它可能不是您理想的解决方案。我不知道与本线程中建议的其他方法相比,它的性能如何。问题是我有两个字符串,而不是两个xml文件。这两个字符串表示从另一个站点发送的xml元素。有什么方法可以将我的字符串转换为XElement或类似的东西吗?这样我就可以遍历它的元素了?要将字符串转换为XElement,可以使用XElement.Parse(yourstring)也可以使用XDocument.Parse(yourstring)将字符串转换为XDocument。Jose Basilio的答案很好,但不完整,它将创建一个包含2个“AllNodes”元素的XElement IEnumerator。更准确的答案是(如果不存在重复的问题):
    xml1.substands(“NodeA”).LastOrDefault().AddAfterSelf(xml2.substands(“NodeA”);xml1.Save()@Vlax这是一个令人伤心的完成,你能告诉我如何将此文件保存为新文件吗?比如,如果xml2被xml1替换,我需要将结果另存为xml3,那么是否可能?出于我自己的需要。还有一个.thankyou@user3510339代码,不过它只保存了第一个XML文件的内容。这是保留还是删除重复项?最简单也是最好的方法。
    
    XElement xFileRoot = XElement.Load(file1.xml);
    XElement xFileChild = XElement.Load(file2.xml);
    xFileRoot.Add(xFileChild);
    xFileRoot.Save(file1.xml);
    
    var combinedUnique = xml1.Descendants()
        .Union(xml2.Descendants());
    combinedUnique.First().Save(#fullName)
    
    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"));
    }