Какой самый быстрый способ объединить два XML-файла в один - PullRequest
25 голосов
/ 11 июня 2009

Если у меня есть две строки 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 ]

44 голосов
/ 11 июня 2009

Самый простой способ сделать это - использовать LINQ to XML. Вы можете использовать Union или Concat в зависимости от ваших потребностей.

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"));
9 голосов
/ 11 июня 2009

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, например, пустой.

4 голосов
/ 04 ноября 2014

Это самый быстрый и чистый способ объединения XML-файлов.

XElement xFileRoot = XElement.Load(file1.xml);
XElement xFileChild = XElement.Load(file2.xml);
xFileRoot.Add(xFileChild);
xFileRoot.Save(file1.xml);
2 голосов
/ 11 июня 2009

Если вы хотите использовать XmlDocument, попробуйте это

 var lNode = lDoc1.ImportNode(lDoc2.DocumentElement.FirstChild, true);
 lDoc1.DocumentElement.AppendChild(lNode);
2 голосов
/ 11 июня 2009

Если вы можете гарантировать этот формат, вы можете объединить их, выполнив манипуляции со строками:

  • Прочитайте первый файл, сохраните все до ""
  • Прочитать второй файл, удалить часть до ""
  • Объедините эти строки.

Это должен быть самый быстрый способ, поскольку анализ не требуется.

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

При этом я всегда предпочел бы безопасный путь быстрому.

1 голос
/ 10 июня 2016

Лучшее для меня решение, основанное на ответе Хосе Базилио, слегка измененное,

var combinedUnique = xml1.Descendants()
    .Union(xml2.Descendants());
combinedUnique.First().Save(#fullName)
1 голос
/ 14 мая 2013

var doc = XDocument.Load ("file1.xml");

var doc1 = XDocument.Load ("file2.xml");

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

1 голос
/ 11 июня 2009

У вас есть два основных варианта:

  1. Разбор XML, объединение структур данных, сериализация обратно в XML.

  2. Если вы знаете структуру, используйте некоторые базовые манипуляции со строками, чтобы взломать ее. Например, в приведенном выше примере вы можете взять внутреннюю часть всех узлов в двух блоках xml и поместить их в один блок всех узлов, и все будет сделано.

0 голосов
/ 16 апреля 2018

В моем случае основное решение не работало , разница была в том, что у меня был Список для тысяч файлов, когда я беру один элемент и пытаюсь слить с первым элементом, я получаю исключение 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"));
}
0 голосов
/ 11 июня 2009

Так как вы запросили самый быстрый :

Если (и только если) структура 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, когда ваши коллеги найдут его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...