12 Replies - 18239 Views - Last Post: 21 January 2008 - 06:31 PM Rate Topic: -----

#4 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 07:25 AM

Ill admit this is the first time Ive tried this in this manner, but Ive written code that is supposed to populate my TreeView from an XML document I created in the project. It's refactored into 2 methods, here they are. First is BuildTreeView:


public void BuildTreeView()
{
	try
	{

		string _XPath = "xml";
		string _rootNode = "FAQList";
		string _filePath = Server.MapPath("XMLFiles/FAQ_List.xml"); //@"e:\\x.xml";
		// Load the XML file .
		XmlDocument doc = new XmlDocument();
		doc.Load(_filePath);
		// Load the XML into the TreeView.
		faqList.Nodes.Clear();
		faqList.Nodes.Add(new TreeNode(_rootNode));
		TreeNode node = new TreeNode();
		node = faqList.Nodes[0];

		XmlNodeList nodes = doc.SelectNodes(_XPath);
		XmlNode xnode = nodes.Item(0).ParentNode;

		AddNode(ref xnode, ref node);

		faqList.CollapseAll();
		faqList.Nodes[0].Expand();
	}

	catch (Exception ex)
	{
		lblMessage.Text = ex.Message;
	}
}
[code]


Now the code that adds the nodes (aptly named [b]AddNode[/b]) follows:


[code]
private void AddNode(ref XmlNode inXmlNode, ref TreeNode inTreeNode)
{
	// Recursive routine to walk the XML DOM and add its nodes to a TreeView.
	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];
			faqList.Nodes.Add(new TreeNode(xNode.Name));
			tNode = faqList.Nodes[i];
			AddNode(ref xNode, ref tNode);
		  
		}
	}
	else
	{
		inTreeNode.Text = inXmlNode.OuterXml.Trim();
	}
}



Anyone see what I'm doing here?
Was This Post Helpful? 1

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5848
  • View blog
  • Posts: 12,707
  • Joined: 16-October 07

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 11:16 AM

Your problem is probably that an XmlNode is pretty generic. Text is an XmlNode, so chances are you're getting more or less than you wanted. The other possible undesired effect is that you're always adding to the top faqList.Nodes.Add(new TreeNode(xNode.Name));, which means you're not getting the treeness you might be looking for.

I would write your example like so, for the leaves:
public void BuildTreeView() {
	XmlDocument doc = new XmlDocument();
	doc.Load(Server.MapPath("XMLFiles/FAQ_List.xml"));
	BuildTreeView(faqList, "FAQList", doc.SelectSingleNode("xml"));
}

private void BuildTreeView(TreeView tv, string rootNodeName, XmlNode rootXmlNode) {
	TreeNode rootTreeNode = new TreeNode(rootNodeName);
	tv.Nodes.Clear();
	tv.Nodes.Add(rootTreeNode);
	AddNode(rootXmlNode, rootTreeNode);
	tv.CollapseAll();
	rootTreeNode.Expand();
}

private void AddNode(XmlNode xmlParentNode, TreeNode treeParentNode) {
	if (!xmlParentNode.HasChildNodes) { return; }
	foreach(XmlNode xmlNode in xmlParentNode.ChildNodes) {
		TreeNode treeNode = new TreeNode(xmlNode.Name);
		treeParentNode.ChildNodes.Add(treeNode);
		AddNode(xmlNode, treeNode);
	}
}



For best results, though, I'd want to customize code to the data and use xpath to get known Elements and treat them as such.

Using this file:
<?xml version="1.0" encoding="utf-8" ?>
<faqList>
	<faq label="Topic 1">XML is Fun</faq>
	<faq label="Topic 2">XSL is Also Fun</faq>
	<faq label="Bigger Topic">
		<faq label="Big Topic 1">Not all nodes are elements.</faq>
		<faq label="Big Topic 2">All elements are nodes.</faq>
	</faq>
</faqList>	



Here's more specific code:
public void BuildTreeView() {
	XmlDocument doc = new XmlDocument();
	doc.Load(Server.MapPath("data.xml"));
	BuildTreeView(this.TreeView1, "FAQList", doc.SelectSingleNode("//faqList"), "faq", "label");
}

private void BuildTreeView(TreeView tv, string rootNodeName, XmlNode rootXmlNode, string xmlElementName, string nameAttr) {
	TreeNode rootTreeNode = new TreeNode(rootNodeName);
	tv.Nodes.Clear();
	tv.Nodes.Add(rootTreeNode);
	AddNode(rootXmlNode, rootTreeNode, xmlElementName, nameAttr);
	tv.CollapseAll();
	rootTreeNode.Expand();
}

private void AddNode(XmlNode xmlParentNode, TreeNode treeParentNode, string xmlElementName, string nameAttr) {
	foreach (XmlElement xmlEle in xmlParentNode.SelectNodes(xmlElementName)) {
		TreeNode treeNode = new TreeNode(xmlEle.GetAttribute(nameAttr));
		treeParentNode.ChildNodes.Add(treeNode);
		AddNode(xmlEle, treeNode, xmlElementName, nameAttr);
	}
}



An improvement here would be to also address urls. If you include those in the xml and scoop them out, your custom tree filler is pretty much done.

Hope it helps.
Was This Post Helpful? 0
  • +
  • -

#6 Jayman  Icon User is offline

  • Student of Life
  • member icon

Reputation: 418
  • View blog
  • Posts: 9,532
  • Joined: 26-December 05

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 12:46 PM

Since you didn't post your XML file I am not 100% sure that this is the problem. But I believe the problem lies in your _XPath.

MSDN XPath Navigation

Assuming "xml" are child nodes in the XML file. You might try changing it to:

string _XPath = "descendant::xml";

Was This Post Helpful? 0
  • +
  • -

#7 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 08:42 PM

Thanks for everyone's help. I m attempting to co this for a FAQ section for a web application. Since Im not what I would call an XML Guru, I'm having a hard time putting the XML document together, imagine that lol
Was This Post Helpful? 0
  • +
  • -

#8 Jayman  Icon User is offline

  • Student of Life
  • member icon

Reputation: 418
  • View blog
  • Posts: 9,532
  • Joined: 26-December 05

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 09:14 PM

So is the problem your having reading the XML file or just creating the XML file itself. You never really clearly state the issue that you are having.

If the problem is reading the XML file then describe what you want vs what you are actually getting for output.

If the problem is creating the XML file, then describe what you need and we will help you create the schema.

As you well know, the more information you give us then a more accurate an answer we can provide. :)
Was This Post Helpful? 0
  • +
  • -

#9 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 09:35 PM

Sorry, for the misunderstanding. Im trying to create a FAQ section using a TreeView and an XML document (weird, I posted this same post like 3 minutes ago and now its gone). The XML document Im using is:


<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<FAQList>
  <FAQ>
	  <Question>Can I change the look of the site, or use different skins?</Question>
	  <Answer>Skins wil be available in Version 2 of A.M.I.O. It is definatey something on our list to add as a feature.</Answer>
  </FAQ>
  <FAQ>
	  <Question>What is my music directory changes?</Question>
	  <Answer>You will be given the opportunity to provide your new music directory</Answer>
  </FAQ>
  <FAQ>
	<Question>What information is stored about me?</Question>
	<Answer>
	  The only information we store at this time is the directory of your music, your name, and when we add in the <i>skin</i> functionality
	  the information holding the skin will be stored as well.
	</Answer>
  </FAQ>
  <FAQ>
	  <Question>Will I be able to create a playlist?</Question>
	  <Answer>The creation of playlist is a vital part of Version 1.0 of A.M.I.O, so editing them, rearranging them, etc.</Answer>
  </FAQ>
</FAQList>




The code Im using to try and parse this document and populate my tree is:


private void FillTree()
{
	string _filePath = Server.MapPath("XMLFiles/FAQ_List.xml");
	XmlDocument doc = new XmlDocument();
	doc.LoadXml(_filePath);
	TreeNode faqNode;
	TreeNode faqAnswerNode;
	foreach (XmlNode node in doc.SelectNodes("FAQList/FAQ"))
	{
		string question = node.SelectSingleNode("//Question").InnerText;
		faqNode = new TreeNode();
		faqNode.Text = String.Format("Q:  {0}",question );
		faqList.Nodes.Add(faqNode);
		foreach (XmlNode itemNode in node.SelectNodes("FAQList/FAQ"))
		{
			string answer = itemNode.SelectSingleNode("//Answer").InnerText;
			faqAnswerNode = new TreeNode();
			faqAnswerNode.Text = String.Format("A:  {0}", answer);
			faqList.Nodes.Add(faqAnswerNode);
		}
	}
}




But when I try to load the page I get the following message:


Quote

Exception Details: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.



So XML Guru's, where am I going wrong?
Was This Post Helpful? 0
  • +
  • -

#10 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Populate TreeView from XML File {Resolved}

Posted 20 January 2008 - 11:41 PM

Well this is the code Ive come up with (based on the XML shown in last post) but I am getting an error on the line marked with a <<<


private void AddNode(XmlNode xmlNode, TreeNode treeNode)
{
	XmlNode questionNode;
	TreeNode answerNode;
	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 (xmlNode.HasChildNodes)
	{
		nodeList = xmlNode.ChildNodes;
		for (i = 0; i <= nodeList.Count - 1; i++)
		{
			questionNode = xmlNode.ChildNodes[i];
			treeNode.Nodes.Add(new TreeNode(questionNode.Name)); <<<
			answerNode = treeNode.Nodes[i]; 
			AddNode(questionNode, answerNode);
		}
	}
	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.
		treeNode.Text = (xmlNode.OuterXml).Trim();
	}
}		   




The error message I'm receiving is:


Quote

'System.Web.UI.WebControls.TreeNode' does not contain a definition for 'Nodes'



I wrote this for a Windows Form I was working on, but now Im trying to convert it to web and not having too much luck myself
Was This Post Helpful? 0
  • +
  • -

#11 Jayman  Icon User is offline

  • Student of Life
  • member icon

Reputation: 418
  • View blog
  • Posts: 9,532
  • Joined: 26-December 05

Re: Populate TreeView from XML File {Resolved}

Posted 21 January 2008 - 12:12 AM

Quote

But when I try to load the page I get the following message:

Exception Details: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.

You need to use the Load method, instead of XmlLoad to acquire the XML file. XmlLoad is used if you are passing the entire XML document as a string. If you are loading a document from a file then use the Load method.
doc.Load(_filePath);



Quote

'System.Web.UI.WebControls.TreeNode' does not contain a definition for 'Nodes'

In response to your second post about the web application, the problem here is that you have to use ChildNodes instead of Nodes to load data into the TreeNode. You use Nodes if you are referring to the TreeView, not a TreeNode.

	private void AddNode(XmlNode xmlNode, TreeNode treeNode)
	{
		XmlNode questionNode;
		TreeNode answerNode;
		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 (xmlNode.HasChildNodes)
		{
			nodeList = xmlNode.ChildNodes;
			for (i = 0; i <= nodeList.Count - 1; i++)
			{
				questionNode = xmlNode.ChildNodes[i];
				treeNode.ChildNodes.Add(new TreeNode(questionNode.Name));
				answerNode = treeNode.ChildNodes[i];
				AddNode(questionNode, answerNode);
			}
		}
		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.
			treeNode.Text = (xmlNode.OuterXml).Trim();
		}
	}

Was This Post Helpful? 0
  • +
  • -

#12 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5848
  • View blog
  • Posts: 12,707
  • Joined: 16-October 07

Re: Populate TreeView from XML File {Resolved}

Posted 21 January 2008 - 05:43 AM

Your xml looks fine. However, the use of // will definitely hurt you. The syntax means, return all, regardless of position in document. It does a full document scan, no matter what. So, node.SelectSingleNode("//Question") will return the first "Question" node of the document, every time.


Without testing, this might do it:
private void FillTree() {
	XmlDocument doc = new XmlDocument();
	doc.LoadXml(Server.MapPath("XMLFiles/FAQ_List.xml"));
	
	// get all FAQ nodes in doc, we don't care where
	foreach (XmlNode xmlNode in doc.SelectNodes("//FAQ")) {
		// now we're local, no //, etc, should be required.
		string question = xmlNode.SelectSingleNode("Question").InnerText;
		string answer = xmlNode.SelectSingleNode("Answer").InnerText;
		
		//Make two tree nodes
		TreeNode faqNode = new TreeNode(String.Format("Q:  {0}",question ));
		TreeNode faqAnswerNode = new TreeNode(String.Format("A:  {0}", answer));
		
		// put the answer node under the question node
		faqNode.Nodes.Add(faqAnswerNode);
		
		// and add to tree
		faqList.Nodes.Add(faqNode);
	}
}



Of course, treeViews seem to loose it if the names are too long...
Was This Post Helpful? 0
  • +
  • -

#13 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Populate TreeView from XML File {Resolved}

Posted 21 January 2008 - 09:07 AM

Thank you two so much! I dont run into this kind of problem often, but when I do its nice to know where I can find the help I need.

Got rid of all the errors, but the FAQ's aren't exactly listed right, I was (am) trying to the question to be listed (with the little + sign saying theres an answer), but for right now its displaying like this, how can I change this, or is there a way?

Attached Image
Was This Post Helpful? 0
  • +
  • -

#14 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5848
  • View blog
  • Posts: 12,707
  • Joined: 16-October 07

Re: Populate TreeView from XML File {Resolved}

Posted 21 January 2008 - 10:42 AM

View PostPsychoCoder, on 21 Jan, 2008 - 11:07 AM, said:

I was (am) trying to the question to be listed (with the little + sign saying theres an answer)


I think the last one I posted should be close to this. :P

I've found treeview ultimately force me to consider other directions. There used to be something about them only displaying text, not formatted HTML. Hope they fixed that. Good luck.
Was This Post Helpful? 0
  • +
  • -

#15 Jayman  Icon User is offline

  • Student of Life
  • member icon

Reputation: 418
  • View blog
  • Posts: 9,532
  • Joined: 26-December 05

Re: Populate TreeView from XML File {Resolved}

Posted 21 January 2008 - 05:39 PM

Ahh, now I understand what you want in your output.

Making the following changes will give you the result you desire.

string _XPath = "descendant::FAQ";


	private void AddNode(XmlNode xmlNode, TreeNode treeNode)
	{
		TreeNode faqNode;
		XmlNodeList nodeList;

		// Loop through the XML nodes until the leaf is reached.
		// Add the nodes to the TreeView during the looping process.
		if (xmlNode.HasChildNodes)
		{
			nodeList = xmlNode.ChildNodes;

			foreach(XmlNode node in nodeList)
			{
				faqNode = new TreeNode(node["Question"].InnerText);
				faqNode.ChildNodes.Add(new TreeNode(node["Answer"].InnerText));
				treeNode.ChildNodes.Add(faqNode);
			}
		}
		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.
			treeNode.Text = (xmlNode.OuterXml).Trim();
		}
	}


Here is a screen shot of the output. Enjoy!

Attached image(s)

  • Attached Image

Was This Post Helpful? 0
  • +
  • -

#16 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Re: Populate TreeView from XML File {Resolved}

Posted 21 January 2008 - 06:31 PM

Thanks to both jayman and baavgai, sometimes when it comes to working with XML I get kind of confused and lost, but its nice that we have DIC here for help ain't it?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1