"Combinación automática de XML" suena como un requisito relativamente simple, pero cuando se analizan todos los detalles, se vuelve complejo bastante rápido. Combinar con C# o XSLT será mucho más fácil para tareas más específicas, como en el modelo answer para EF. El uso de herramientas para ayudar con una fusión manual también puede ser una opción (consulte this SO question).
Para la referencia (y para dar una idea de la complejidad) He aquí un ejemplo de código abierto del mundo Java: XML merging made easy
Volver a la pregunta original.Hay pocas áreas grises grandes en la especificación de la tarea: cuando se deben considerar 2 elementos equivalente (tienen el mismo nombre, coinciden los atributos seleccionados o todos, o también tienen la misma posición en el elemento padre); cómo manejar la situación cuando XML original o fusionada tiene múltiples equivalentes elementos etc.
El código siguiente es suponiendo que
- que sólo se preocupan por los elementos en el momento
- elementos son equivalentes si los nombres de los elementos, los nombres de los atributos y los valores de los atributos coinciden con
- un elemento no tiene múltiples atributos con el mismo nombre
- todos equivalentes elementos del documento combinado se combinarán con el primer elemento equivalente en el documento XML de origen.
.
// determine which elements we consider the same
//
private static bool AreEquivalent(XElement a, XElement b)
{
if(a.Name != b.Name) return false;
if(!a.HasAttributes && !b.HasAttributes) return true;
if(!a.HasAttributes || !b.HasAttributes) return false;
if(a.Attributes().Count() != b.Attributes().Count()) return false;
return a.Attributes().All(attA => b.Attributes(attA.Name)
.Count(attB => attB.Value == attA.Value) != 0);
}
// Merge "merged" document B into "source" A
//
private static void MergeElements(XElement parentA, XElement parentB)
{
// merge per-element content from parentB into parentA
//
foreach (XElement childB in parentB.DescendantNodes())
{
// merge childB with first equivalent childA
// equivalent childB1, childB2,.. will be combined
//
bool isMatchFound = false;
foreach (XElement childA in parentA.Descendants())
{
if (AreEquivalent(childA, childB))
{
MergeElements(childA, childB);
isMatchFound = true;
break;
}
}
// if there is no equivalent childA, add childB into parentA
//
if (!isMatchFound) parentA.Add(childB);
}
}
se va a producir el resultado deseado con los fragmentos XML originales, pero si XMLs de entrada son más complejos y tienen elementos duplicados, el resultado será más interesante ...:
public static void Test()
{
var a = XDocument.Parse(@"
<Root>
<LeafA>
<Item1 />
<Item2 />
<SubLeaf><X/></SubLeaf>
</LeafA>
<LeafB>
<Item1 />
<Item2 />
</LeafB>
</Root>");
var b = XDocument.Parse(@"
<Root>
<LeafB>
<Item5 />
<Item1 />
<Item6 />
</LeafB>
<LeafA Name=""X"">
<Item3 />
</LeafA>
<LeafA>
<Item3 />
</LeafA>
<LeafA>
<SubLeaf><Y/></SubLeaf>
</LeafA>
</Root>");
MergeElements(a.Root, b.Root);
Console.WriteLine("Merged document:\n{0}", a.Root);
}
Aquí hay documento combinado mostrando cómo equivalentes elementos de documento B se combinaron entre sí:
<Root>
<LeafA>
<Item1 />
<Item2 />
<SubLeaf>
<X />
<Y />
</SubLeaf>
<Item3 />
</LeafA>
<LeafB>
<Item1 />
<Item2 />
<Item5 />
<Item6 />
</LeafB>
<LeafA Name="X">
<Item3 />
</LeafA>
</Root>
Cortar y pegar dentro de un editor de texto? – BoltClock
@BoltClock Prefiero una secuencia de comandos ya que estos archivos xml se generan automáticamente y cambian con frecuencia. En este momento mi pequeño tiene aproximadamente 2000 líneas de largo y contiene múltiples áreas que necesitan fusionarse. – Rachel
¿Qué tipo de script? Si hay un idioma preferido para escribir este script, es posible que desee agregarlo a las etiquetas. – BoltClock