Ricorsione, analisi del file xml con attributi in treeview c #

Attualmente sto lavorando a un progetto in cui un’applicazione eseguirà file XML e li visualizzerà in una vista ad albero in C #. Sto usando Visual Studio 10 per scrivere questo codice.

Non posso limitare il numero di volte in cui gli attributi sono visualizzati. Ho usato un ciclo foreach per scorrere in loop ciascuno degli attributi che ha e visualizzarlo, ma sta visualizzando gli attributi una volta per ogni childnode che ha sotto il nodo. Come posso modificare questo codice per visualizzare solo gli attributi una sola volta?

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Xml; namespace xmlToTreeview { public partial class Form1 : Form { string samplePath = Application.StartupPath + @"\\sample.xml"; public Form1() { InitializeComponent(); DisplayTreeView(samplePath); } private void DisplayTreeView(string pathname) { try { // SECTION 1. Create a DOM Document and load the XML data into it. XmlDocument dom = new XmlDocument(); dom.Load(pathname); // SECTION 2. Initialize the TreeView control. treeView1.Nodes.Clear(); treeView1.Nodes.Add(new TreeNode(dom.DocumentElement.Name)); TreeNode tNode = new TreeNode(); tNode = treeView1.Nodes[0]; // SECTION 3. Populate the TreeView with the DOM nodes. AddNode(dom.DocumentElement, tNode); } catch (XmlException xmlEx) { MessageBox.Show(xmlEx.Message); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode) { XmlNode xNode; TreeNode tNode; XmlNodeList nodeList; int i; // Loop through the XML nodes until the leaf is reached. // Add the nodes to the TreeView during the looping process. if (inXmlNode.HasChildNodes) { nodeList = inXmlNode.ChildNodes; for (i = 0; i <= nodeList.Count - 1; i++) { xNode = inXmlNode.ChildNodes[i]; inTreeNode.Nodes.Add(new TreeNode(xNode.Name)); tNode = inTreeNode.Nodes[i]; //Check if the XmlNode has attributes if (inXmlNode.Attributes.Count != 0) { foreach (XmlAttribute att in inXmlNode.Attributes) { inTreeNode.Text = inTreeNode.Text + " " + att.Name + ": " + att.Value; } } AddNode(xNode, tNode); } } else { // Here you need to pull the data from the XmlNode based on the // type of node, whether attribute values are required, and so forth. inTreeNode.Text = (inXmlNode.OuterXml).Trim(); } treeView1.ExpandAll(); } } } 

Ed ecco un esempio del mio xml

       
I'm breaking here God I'm breaking here again, i hope you can fix me cry face myname yourname yourname typeme visionme ohno --> idk idk idk

È necessario spostare il ciclo attraverso gli attributi fuori dal ciclo attraverso i nodes figlio:

  private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode) { // Loop through the XML nodes until the leaf is reached. // Add the nodes to the TreeView during the looping process. if (inXmlNode.HasChildNodes) { //Check if the XmlNode has attributes foreach (XmlAttribute att in inXmlNode.Attributes) { inTreeNode.Text = inTreeNode.Text + " " + att.Name + ": " + att.Value; } var nodeList = inXmlNode.ChildNodes; for (int i = 0; i < nodeList.Count; i++) { var xNode = inXmlNode.ChildNodes[i]; var tNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(xNode.Name))]; AddNode(xNode, tNode); } } else { // Here you need to pull the data from the XmlNode based on the // type of node, whether attribute values are required, and so forth. inTreeNode.Text = (inXmlNode.OuterXml).Trim(); } treeView1.ExpandAll(); } 

Aggiornare

Se si desidera filtrare gli attributi dello spazio dei nomi, è ansible aggiungere i metodi di estensione :

 public static class XmlNodeExtensions { public static bool IsDefaultNamespaceDeclaration(this XmlAttribute attr) { if (attr == null) return false; if (attr.NamespaceURI != "http://www.w3.org/2000/xmlns/") return false; return attr.Name == "xmlns"; } public static bool IsNamespaceDeclaration(this XmlAttribute attr) { if (attr == null) return false; if (attr.NamespaceURI != "http://www.w3.org/2000/xmlns/") return false; return attr.Name == "xmlns" || attr.Name.StartsWith("xmlns:"); } } 

Quindi XmlAttribute per saltare le istanze XmlAttribute indesiderate. È inoltre ansible impostare in modo esplicito il testo di tutti i nodes di tipo XmlElement come nomi + attributi, non solo quegli elementi con elementi OuterXml , utilizzando OuterXml solo per i nodes di testo:

  private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode) { if (inXmlNode is XmlElement) { // An element. Display element name + attribute names & values. foreach (var att in inXmlNode.Attributes.Cast().Where(a => !a.IsNamespaceDeclaration())) { inTreeNode.Text = inTreeNode.Text + " " + att.Name + ": " + att.Value; } // Add children foreach (XmlNode xNode in inXmlNode.ChildNodes) { var tNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(xNode.Name))]; AddNode(xNode, tNode); } } else { // Not an element. Character data, comment, etc. Display all text. inTreeNode.Text = (inXmlNode.OuterXml).Trim(); } treeView1.ExpandAll(); } 

Se vuoi davvero filtrare solo le definizioni dello spazio dei nomi predefinite ma ne lasci altre, puoi fare:

  // An element. Display element name + attribute names & values. foreach (var att in inXmlNode.Attributes.Cast().Where(a => !a.IsDefaultNamespaceDeclaration())) { inTreeNode.Text = inTreeNode.Text + " " + att.Name + ": " + att.Value; } 

Per inciso, non consiglio di fare questo dato che il seguente in realtà significa la stessa cosa, vale a dire un elemento con nome locale DataConfiguration nello spazio dei nomi http://somenamespace :

   

Il tuo albero mostrerà lo spazio dei nomi per il primo elemento ma non il secondo.

Aggiornamento 2

Per includere XmlDeclaration nell'albero, modifica il loop di livello superiore in modo che sia:

  treeView1.Nodes.Clear(); foreach (XmlNode xNode in dom.ChildNodes) { var tNode = treeView1.Nodes[treeView1.Nodes.Add(new TreeNode(xNode.Name))]; AddNode(xNode, tNode); } 

Aggiornamento 3

Inserire il ciclo per includere il ciclo XmlDeclaration in DisplayTreeView :

  private void DisplayTreeView(string pathname) { try { // SECTION 1. Create a DOM Document and load the XML data into it. XmlDocument dom = new XmlDocument(); dom.Load(pathname); // SECTION 2. Initialize the TreeView control. treeView1.Nodes.Clear(); // SECTION 3. Populate the TreeView with the XML nodes. foreach (XmlNode xNode in dom.ChildNodes) { var tNode = treeView1.Nodes[treeView1.Nodes.Add(new TreeNode(xNode.Name))]; AddNode(xNode, tNode); } } catch (XmlException xmlEx) { MessageBox.Show(xmlEx.Message); } catch (Exception ex) { MessageBox.Show(ex.Message); } } 

Prova semplice algoritmo ricorsivo

  static void Main(string[] args) { string input = "" + "" + "val1" + "val2" + "" + "val3" + "val4" + ""; XmlDocument doc = new XmlDocument(); doc.LoadXml(input); RecursiveRead(doc.DocumentElement); } static string RecursiveRead(XmlNode node) { List children = new List(); bool done = false; if (node.HasChildNodes) { foreach (XmlNode child in node) { children.Add(RecursiveRead(child)); } Console.WriteLine("table : {0}; children : {1}", node.Name, string.Join(",", children.ToArray())); //string cmd = "INSERT INTO " + second + " (" + first + ") VALUES ('" + xml.Value + "')"; //SqlCommand command = new SqlCommand(cmd, conn); //command.ExecuteNonQuery(); } else { return node.Value; } return node.Name; }