2011-10-11 14 views
12

Todas las soluciones que he encontrado con respecto a la fusión de documentos XML no logran lo que deseo. Me explico:Fusión de documentos xml

XML Documento 1:

<?xml version="1.0" encoding="utf-8" ?> 
<a> 
    <b title="Original Section"> 
     <b title="Original Child Section"></b> 
     <b title="Original Child Section 2"></b> 
    </b> 
</a> 

XML Documento 2:

<?xml version="1.0" encoding="utf-8" ?> 
<a> 
    <b title="New Section"> 
     <b title="New Child Section"></b> 
    </b> 
    <b title="Original Section"> 
     <b title="Original Child Section"> 
      <b title="New Child For Old Section"></b> 
     </b> 
    </b>  
</a> 

En un documento final de la siguiente manera:

<?xml version="1.0" encoding="utf-8" ?> 
<a> 
    <b title="Original Section"> 
     <b title="Original Child Section"> 
      <b title="New Child For Old Section"></b> 
     </b> 
     <b title="Original Child Section 2"></b> 
    </b>  
    <b title="New Section"> 
     <b title="New Child Section"></b> 
    </b> 
</a> 

Los documentos son similares en su contenido , pero puede tener una cantidad arbitraria de nodos secundarios. También me gustaría eliminar duplicados. Considero que los duplicados son elementos con los mismos atributos (basados ​​en el nombre y el valor del atributo). ¿Alguien ha visto un ejemplo funcional de esta implementación? Puedo imaginar cómo lo escribiría usando algunos bucles y un poco de recursión, pero para mí, eso simplemente no parece ser la mejor manera de lograr lo que quiero :)

¡Salud y gracias de antemano!

* EDITAR *

Dado que el consenso es que los bucles y recursividad son una necesidad, ¿cuál sería la forma más elegante y eficiente para lograr esto? Supongo que otra pregunta fundamental para este problema es ¿cuál es la mejor forma de comparar los nodos mientras iteras?

+2

Implementé algo como esto para un cliente. Básicamente funciona de la manera en que lo implementaría: uso de bucles y recursión. –

+2

+1 para buen ejemplo –

+0

Estoy de acuerdo con @DanielHilgarth. Looping y recursing es básicamente la forma más sencilla de lograr esto. – Kian

Respuesta

1

Eventualmente, cualquier solución a este problema se reducirá a bucles y/o recursión. Estás hablando de teoría de conjuntos básica, y linq puede ser útil para destilar el proceso, pero en última instancia se repetirá en ambos conjuntos y se fusionarán los resultados.

+0

Eso es lo que pensé. Entonces supongo que debería modificar mi pregunta para pedir la solución más elegante y eficiente para este problema. – nokturnal

1

Escribiría un IEqualityComparer que especifica cuándo dos nodos son 'coincidentes' - es decir, establece la regla de coincidencia de título.

class XElementComparer : IEqualityComparer<XElement> 
{ 
    public bool Equals(XElement x, XElement y) 
    { 
     var xTitle = x.Attribute("title"); 
     var yTitle = y.Attribute("title"); 

     if (xTitle == null || yTitle == null) return false; 

     return xTitle.Value == yTitle.Value; 
    } 

    public int GetHashCode(XElement obj) 
    { 
     return base.GetHashCode(); 
    } 
} 

y luego escribir un método recursivo que arrastre a través de su XML, la fusión de nodos que coinciden acuerdo con el comparador.

private XElement Merge(XElement node1, XElement node2) 
{ 
    // trivial cases 
    if (node1 == null) return node2; 
    if (node2 == null) return node1; 

    var elements1 = node1.Elements(); 
    var elements2 = node2.Elements(); 

    // create a merged root 
    var result = new XElement(node1.Name, node1.Attribute("title")); 

    var comparer = new XElementComparer(); 
    var mergedNodes = elements1.Union(elements2, comparer).ToList(); 

    // for the union of the elements, insert their merge values 
    foreach (var title in mergedNodes) 
    { 
     var child1 = elements1.SingleOrDefault(e => comparer.Equals(e, title)); 
     var child2 = elements2.SingleOrDefault(e => comparer.Equals(e, title)); 

     result.Add(Merge(child1, child2)); 
    } 

    return result; 
} 
+0

Sé que los nombres de las variables son un poco comunes y debería haber implementado apropiadamente 'GetHashCode', pero los conceptos básicos están ahí. –

+0

Esto parece MUY prometedor. Es exactamente como me estaba acercando al tema, pero mucho más inteligente :) Permítanme meterme con eso y ver qué puedo pensar – nokturnal

Cuestiones relacionadas