c# xml: muestra solo un elemento/nodo si los nombres de los elementos son iguales

Este es el proyecto .NET 2.0. En primer lugar, el xml i qué analizar:

<?xml version="1.0" standalone="yes"?>
<DocumentElement>
  <diagramer>
    <PKTABLE_NAME>TECH_Y_Category</PKTABLE_NAME>
    <FKTABLE_NAME>TECH_File</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>TECH_File</PKTABLE_NAME>
    <FKTABLE_NAME>TECH_Version</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>TECH_Group</PKTABLE_NAME>
    <FKTABLE_NAME>TECH_D_Group_File_Version</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>TECH_Layout</PKTABLE_NAME>
    <FKTABLE_NAME>TECH_File</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>CK_List</PKTABLE_NAME>
    <FKTABLE_NAME>CK_Vote</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>CK_List</PKTABLE_NAME>
    <FKTABLE_NAME>CK_Score</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>TECH_Page</PKTABLE_NAME>
    <FKTABLE_NAME>TECH_Page</FKTABLE_NAME>
  </diagramer>
  <diagramer>
    <PKTABLE_NAME>CK_List</PKTABLE_NAME>
    <FKTABLE_NAME>Comments</FKTABLE_NAME>
  </diagramer>
</DocumentElement>

Como puede ver, algunos valores de PKTABLE_NAME son iguales. Estoy recorriendo ese xml usando el siguiente código:

StringBuilder sb = new StringBuilder();
foreach (XmlNode items in diagramTables)
{
  string pkTable = items["PKTABLE_NAME"].InnerText.Replace("_",@"\_");
  string fkTable = items["FKTABLE_NAME"].InnerText.Replace("_",@"\_");

  sb.Append(pkTable);
  sb.Append(" got ");
  sb.Append( fkTable + Environment.NewLine);

}

No es exactamente lo que quiero lograr. Quiero tener todos los valores pero solo una vez (no quiero repetirlos). después de todo, quiero escribir algo como esto desde xml arriba:

  • TECH_Y_Categoría tiene Archivo_TECH
  • Archivo_TECH tiene Versión_TECNOLOGÍA
  • TECH_Grupo tiene TECH_D_Group_File_Version
  • TECH_Layout tiene Archivo_TECH
  • CK_Lista tiene CK_Voto | Puntuación_CK | Comentarios
  • TECH_Página tiene TECH_Página

Espero que entiendas lo que estoy tratando de lograr.

EDITAR.

El código de Morawski funcionó perfectamente para mí, así que el problema está resuelto;).

preguntado el 31 de julio de 12 a las 11:07

2 Respuestas

Algo como:

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
foreach (XmlNode items in diagramTables)
{
  string pkTable = items["PKTABLE_NAME"].InnerText.Replace("_",@"\_");
  string fkTable = items["FKTABLE_NAME"].InnerText.Replace("_",@"\_");
  if (!dict.ContainsKey(pkTable))
  {
    dict.Add(pkTable, new List<string>());
  }
  if (!dict[pkTable].Contains(fkTable))
  {
      dict[pkTable].Add(fkTable);
  }
}
sb.Append("========================================================="); // making it easier for you
foreach(KeyValuePair<string, List<string>> kvp in dict)
{
  sb.Append(kvp.Key);
  sb.Append(" got ");
  sb.AppendLine(String.Join("|", kvp.Value.ToArray()));
}
sb.Append("========================================================="); // making it easier for you

Respondido 01 ago 12, 12:08

Como dije, es un proyecto .NET 2.0;). No puedo usar la palabra clave var. ¿Hay otra solución a eso? - nacido2fr4g

Lo siento, olvidé que no había var antes de .NET 3.0. Actualicé mi código en consecuencia. var no es nada realmente, solo una notación abreviada para lo mismo. - Konrad Morawski

Gracias :). Probé esto y el resultado es así -> mire el primer comentario. - nacido2fr4g

Eso es físicamente imposible. Un diccionario no puede contener claves duplicadas. Apuesto a que solo las últimas 6 líneas de la salida impresa en realidad provienen de mi código; lo más probable es que hayas olvidado borrar el tuyo sb.Appends desde el primero foreach bucle o algo. Solo asegúrate de tener el código correcto. - Konrad Morawski

Ver la actualización. ¿Obtienes nombres de tablas duplicados? in entre esas líneas dobles? - Konrad Morawski

Almacenar resultado en un Dictionary of List:

var nodes = new Dictionary<string, List<string>>();

XmlDocument document = new XmlDocument();

foreach (XmlNode childNode in document.ChildNodes)
{
    if(nodes.ContainsKey(childNode.Name))
        nodes[childNode.Name].Add(childNode.InnerText);
    else
        nodes.Add(childNode.Name, new List<string> {childNode.InnerText});
}

// and printing

foreach (var node in nodes)
{
    string values = node.Value.Aggregate("", (current, s) => current + ("|" + s));
    Console.WriteLine(node.Key + " gots " + values);
}

Respondido 31 Jul 12, 11:07

Es más o menos la misma solución que la mía, su código, por alguna coincidencia, incluso contiene kvp.Value.ToArray(), aunque su variable de iteración no se nombra kvp en absoluto (solo el mío es) :)) - Konrad Morawski

;) ¡Ups! sí. Soy un tipper lasy. agrego a mi manera - Ria

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.