web-dev-qa-db-fra.com

Quel est le moyen le plus rapide de combiner deux fichiers XML en un seul

Si j'ai deux chaînes de xml1 et xml2 qui représentent toutes les deux xml dans le même format. Quel est le moyen le plus rapide de les combiner? Le format n'est pas important, mais je veux juste savoir comment puis-je me débarrasser ou?

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>

et avoir quelque chose comme ça: 

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

La méthode la plus simple consiste à utiliser LINQ to XML. Vous pouvez utiliser Union ou Concat en fonction de vos besoins.

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"));
43
Jose Basilio

Une transformation XSLT pourrait le faire:

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

Transmettez les noms des fichiers en tant que paramètres, ainsi que le nom du nouvel élément racine.

Appliquer à tout document XML, par exemple. un vide.

8
Tomalak

C'est le moyen le plus rapide et le plus propre de fusionner des fichiers XML.

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

Si vous pouvez garantir ce format, vous pouvez les combiner en manipulant des chaînes:

  • Lire le premier fichier, tout conserver avant "</ AllNodes>"
  • Lire le deuxième fichier, supprimer la partie jusqu'à "<AllNodes>"
  • Combinez ces chaînes.

Cela devrait être le moyen le plus rapide, car aucune analyse n'est nécessaire.

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

Cela dit, je préférerais toujours le moyen sûr au moyen rapide.

2
VVS

Si vous voulez utiliser XmlDocument, essayez ceci

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

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

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

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

1
Heba El-Fadly

Vous avez deux options de base:

  1. Analyser le XML, combiner les structures de données, sérialiser en XML.

  2. Si vous connaissez la structure, utilisez une manipulation de chaîne de base pour la pirater. Par exemple, dans l'exemple ci-dessus, vous pouvez prendre l'intérieur de tous les noeuds dans les deux blocs XML et les placer dans un seul bloc allnodes.

1
Alan Jackson

La meilleure solution pour moi, basée sur la réponse de Jose Basilio, légèrement modifiée,

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

Dans mon cas la solution principale ne fonctionnait pas bien , la différence était que j'avais une liste pour des milliers de fichiers lorsque je prenais un élément et que je tentais de le fusionner avec le premier élément que j'avais pour exception modèle avec et ligne vide (NodeA dans ce cas) pour résoudre le problème étrange de la mémoire et s’exécuter sans à-coups.

Je sauvegarde le document dans un autre processus

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
Eduardo Chávez

Si je faisais cela (en utilisant C #), je créerais une classe dans laquelle je peux désérialiser ce XML (vous pouvez utiliser xsd.exe pour le faire), puis faire une boucle sur tous les nœuds de l'objet représentant le premier morceau de XML. et "Ajoutez" à la propriété AllNodes de l'objet représentant le deuxième XML.

Puis sérialisez la seconde classe en arrière sur le XML, et cela devrait ressembler à votre 3ème exemple.

0
Sam Schutte

Depuis que vous avez demandé le le plus rapide

Si (et seulement si) la structure XML est toujours cohérente: (c'est du pseudo code)

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

C'est un hack géant mais c'est rapide. Attendez-vous à le voir sur TheDailyWTF lorsque vos collègues le trouvent.

0
rein