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>
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"));
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.
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);
Si vous pouvez garantir ce format, vous pouvez les combiner en manipulant des 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.
Si vous voulez utiliser XmlDocument, essayez ceci
var lNode = lDoc1.ImportNode(lDoc2.DocumentElement.FirstChild, true);
lDoc1.DocumentElement.AppendChild(lNode);
var doc = XDocument.Load ("fichier1.xml");
var doc1 = XDocument.Load ("fichier2.xml");
doc.Root.Add (doc2.Root.Elements ());
Vous avez deux options de base:
Analyser le XML, combiner les structures de données, sérialiser en XML.
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.
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)
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"));
}
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.
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.