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

时间:2009-06-11 17:48:37

标签: c# xml

如果我有两个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>

11 个答案:

答案 0 :(得分:44)

最简单的方法是使用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"));

答案 1 :(得分:8)

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文档,例如一个空的。

答案 2 :(得分:4)

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

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

答案 3 :(得分:2)

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

  • 阅读第一个文件,保留“&lt; / AllNodes&gt;”
  • 之前的所有内容
  • 阅读第二个文件,将部分删除至“&lt; AllNodes&gt;”
  • 合并这些字符串。

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

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

那就是说我总是喜欢快速通道的安全方式。

答案 4 :(得分:2)

如果要使用XmlDocument,请尝试使用

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

答案 5 :(得分:1)

您有两个基本选项:

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

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

答案 6 :(得分:1)

var doc = XDocument.Load(“file1.xml”);

var doc1 = XDocument.Load(“file2.xml”);

doc.Root.Add(doc2.Root.Elements());

答案 7 :(得分:1)

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

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

答案 8 :(得分:0)

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

然后将第二个类序列化为XML,它应该看起来像你的第三个例子。

答案 9 :(得分:0)

由于您要求最快

如果(且仅当)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);

这是一个巨大的黑客,但它很快。当你的同事找到它时,期待在TheDailyWTF上看到它。

答案 10 :(得分:0)

在我的情况下主要解决方案效果不佳,不同之处在于,当我拿一个元素并尝试与第一个元素合并时,我有一个数千个文件的List我得到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"));
}