I have a trouble with Expand / Collapse icon in TreeView
What I get : http://i.imgur.com/dl5Lg.jpg
What I did :
C# code :
public static void TreeLoad(TreeView tree, string #source)
{
XmlDocument document = new XmlDocument();
//TreeView tree = new TreeView();
try
{
if (File.Exists(source))
{
document.Load(source);
tree.Nodes.Clear();
XmlNodeList category = document.SelectNodes("/parent/Categories");
//XmlNodeList links = document.SelectNodes("/parent/Categories/link");
foreach (XmlNode node in category)
{
TreeNode t1 = new TreeNode(node.Attributes["Name"].Value);
tree.Nodes.Add(t1);
//t1.ShowCheckBox = true;
if (node.HasChildNodes)
{
//foreach (XmlNode nod in links)
foreach (XmlNode nod in node.ChildNodes)
{
TreeNode t2 = new TreeNode(nod.Attributes["name"].Value);
tree.Nodes.Add(t2);
}
}
}
//tree.Nodes[0].CollapseAll();
//document.Save(source);
}
else
{
messages = NOTFOUND;
}
}
catch (Exception ect)
{
//exist.InnerText = ect.Message;
messages = ect.Message;
}
finally
{
// document.Save(source);
}
//return tree;
}
URLStorageCtrl.TreeLoad(tree, "example.xml");
ASP.NET code
<asp:TreeView ID="tree" runat="server"></asp:TreeView>
I'm using 4-tier architecture so please do not redirect me to design page, I use only coding.
yeah, of course. you added all nodes to tree as its root.
this code:
tree.Nodes.Add(t2);
change to :
t1.ChildNodes.Add(t2);
Related
I'm working on a Windows Service that uses a xml as on option file to monitor a directory, when a new file is detected in it, this file is renamed, sent by mail to a specified list of users and moved to an archive directory.
The option file used to be like this and the user would replace to what he needs everytime :
<Options>
<ExportDir>path/to/export/directory</ExportDir>
<ArchiveDir>path/to/archive/directory</ArchiveDir>
<MailTo>
<Mail>fake1#mail.com</Mail>
<Mail>fake2#mail.com</Mail>
<Mail>fake3#mail.com</Mail>
</MailTo>
</Options>
Parsing with :
List<string> mail = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(#"path/to/xml/file");
XmlNode NodeExportDir = doc.DocumentElement.SelectSingleNode("ExportDir");
string ExportDir= NodeExportDir.InnerText;
XmlNode NodeArchiveDir = doc.DocumentElement.SelectSingleNode("ArchiveDir");
string ArchiveDir = NodeArchiveDir.InnerText;
XmlNodeList listAddress = doc.SelectNodes("//MailTo");
foreach (XmlNode node in listAddress)
{
foreach (XmlNode mailAddress in node.ChildNodes)
{
mail.Add(mailAddress.InnerText);
}
}
I want to improve it so it is possible to have several options without deleting everytime. So the xml file now looks like :
<Options>
<ExportDir path = "path/to/export/directory">
<ArchiveDir>path/to/archive/directory</ArchiveDir>
<MailTo>
<Mail>fake1#mail.com</Mail>
<Mail>fake2#mail.com</Mail>
<Mail>fake3#mail.com</Mail>
</MailTo>
</ExportDir>
<ExportDir path = "path/to/export/directory2">
<ArchiveDir>path/to/archive/directory2</ArchiveDir>
<MailTo>
<Mail>fake4#mail.com</Mail>
<Mail>fake5#mail.com</Mail>
<Mail>fake6#mail.com</Mail>
</MailTo>
</ExportDir>
</Options>
When there is only one ExportDir, I still manage to parse and put results in needed variables with this code :
List<string> mail = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load(#"path/to/xml/file");
XmlNodeList NodeExportDir = doc.GetElementsByTagName("ExportDir");
for (int i = 0; i < NodeExportDir.Count; i++)
{
string ExportDir = NodeExportDir[i].Attributes["path"].Value;
}
XmlNodeList NodeArchiveDir = doc.SelectNodes("//ArchiveDir");
foreach (XmlNode node in NodeArchiveDir)
{
foreach (XmlNode dirArch in node.ChildNodes)
{
string ArchiveDir = dirArch.InnerText;
}
}
XmlNodeList listAddress = doc.SelectNodes("//MailTo");
foreach (XmlNode node in listAddress)
{
foreach (XmlNode mailAddress in node.ChildNodes)
{
mail.Add(mailAddress.InnerText);
}
}
But when there are more than one, of course it doesn't work as I'd like.
How can I use the archive directory and the mail addresses according to where the user drops a file (which is the ExportDir).
Update :
Thanks to ivcubr's answer I can now select the informations corresponding to an ExportDir path like so :
foreach (DossierExport test in options)
{
if (test.Path == "path/to/export/directory")
{
string ArchiveDir = test.Archive;
foreach (string mailAddr in test.Mail)
{
mail.Add(mailAddr);
}
}
}
How could I make a general solution so I don't have to add code everytime a new ExportDir path is created in the xml file ?
If you are most comfortable with XmlDocument the following should work for you. Here I would recommend creating a class to hold each option and then later you can just loop through all of these and use the properties parsed from the XML file.
XmlDocument doc = new XmlDocument();
doc.Load(#"test.xml");
List<ExportDirectory> options = new List<ExportDirectory>();
XmlNodeList nodeExportDir = doc.GetElementsByTagName("ExportDir");
foreach (XmlNode node in nodeExportDir) {
ExportDirectory exportDirectory = new ExportDirectory() {
Path = node.Attributes["path"].Value,
Archive = node.SelectSingleNode("ArchiveDir").InnerText
};
foreach (XmlNode mail in node.SelectNodes("MailTo/Mail")) {
exportDirectory.Mail.Add(mail.InnerText);
}
options.Add(exportDirectory);
}
Export Directory class:
public class ExportDirectory {
public string Path { get; set; }
public string Archive { get; set; }
public List<string> Mail { get; set; }
public ExportDirectory() {
Mail = new List<string>();
}
}
EDIT:
Regarding your added question, why do you need to have if (test.Path == "path/to/export/directory")? Why not eliminate the if statement and go with:
foreach (DossierExport test in options)
{
string ArchiveDir = test.Archive;
foreach (string mailAddr in test.Mail)
{
mail.Add(mailAddr);
}
}
I am doing a migration tool for sharepoint sites. I migrate sites using XML files. In my method for generating my XML file, however, I get an infinite loop and I can't figure out the cause. I get no errors what so ever but the XML file gets understandably large.
How I create the root node of my XML file:
private void createRootXmlNodeFromRootSite()
{
if (rootsite != null)
{
//Add root-site to TreeView
XmlElement rootnode = document.CreateElement(strRoot);
rootnode.SetAttribute(strTitle, rootsite.Title);
rootnode.SetAttribute(strName, rootsite.SiteAdministrators[0].Name);
rootnode.SetAttribute(strEmail, rootsite.SiteAdministrators[0].Email);
document.AppendChild(rootnode);
XmlElement nodelists = document.CreateElement(strLists);
if (rootsite.Lists.Count > 0)
{
rootnode.AppendChild(nodelists);
//Get all lists within root-site and put them under it's node.
foreach (SPList list in rootsite.Lists)
{
XmlElement nodelist = document.CreateElement(strList);
nodelist.SetAttribute(strTitle, list.Title);
if (!list.Hidden)
{
nodelists.AppendChild(nodelist);
XmlElement nodects = document.CreateElement(strContentTypes);
if (list.ContentTypes.Count > 0)
{
nodelist.AppendChild(nodects);
//Get all content types within lists of root site and put them under it's node.
foreach (SPContentType ct in list.ContentTypes)
{
XmlElement nodect = document.CreateElement(strContentType);
nodect.SetAttribute(strTitle, ct.Name);
if (!ct.Hidden)
{
nodects.AppendChild(nodect);
XmlElement nodefields = document.CreateElement(strFields);
if (ct.Fields.Count > 0)
{
nodect.AppendChild(nodefields);
foreach (SPField field in ct.Fields)
{
XmlElement nodefield = document.CreateElement(strField);
nodefield.SetAttribute(strTitle, field.Title);
if (!field.Hidden)
{
nodefields.AppendChild(nodefield);
}
}
}
}
}
}
}
//Call recursive methods to get child-site-elements.
convertSiteCollectionToXml(rootnode, rootsite);
}
}
}
}
This method then calls a recursive method which creates child nodes from the subsites:
private void convertSiteCollectionToXml(XmlNode nodeElement, SPWeb site)
{
XmlElement nodesites = document.CreateElement("Sites");
if (site.Webs.Count > 0)
{
nodeElement.AppendChild(nodesites);
foreach (SPWeb childsite in site.Webs)
{
XmlElement child = document.CreateElement("Site");
child.SetAttribute("Title", childsite.Title);
nodesites.AppendChild(child);
XmlElement nodelists = document.CreateElement("Lists");
if (childsite.Lists.Count > 0)
{
child.AppendChild(nodelists);
foreach (SPList list in childsite.Lists)
{
XmlElement nodelist = document.CreateElement("List");
nodelist.SetAttribute("Title", list.Title);
if (!list.Hidden)
{
nodelists.AppendChild(nodelist);
XmlElement nodects = document.CreateElement("ContentTypes");
if (list.ContentTypes.Count > 0)
{
nodelist.AppendChild(nodects);
foreach (SPContentType ct in list.ContentTypes)
{
XmlElement nodect = document.CreateElement("ContentType");
nodect.SetAttribute("Title", ct.Name);
if (!ct.Hidden)
{
nodects.AppendChild(nodect);
XmlElement nodefields = document.CreateElement("Fields");
if (ct.Fields.Count > 0)
{
nodect.AppendChild(nodefields);
foreach (SPField field in ct.Fields)
{
XmlElement nodefield = document.CreateElement("Field");
nodefield.SetAttribute("Title", field.Title);
if (!field.Hidden)
{
nodefields.AppendChild(nodefield);
}
}
}
}
}
}
}
convertSiteCollectionToXml(child, childsite);
}
}
}
}
}
The infinite loop happens in the second method. Anyone see the cause?
I want to add to my treeview some nodes with childs, but have a problem how to add nodes with for example ToolTipText. I want do it with TreeNodeCollection.
It is possible or how could I change my code?
Here is my code where all nodes are root nodes.
protected void CreateTreeView(TreeNodeCollection parentNode, int parentID, DataTable mytab)
{
foreach (DataRow dta in mytab.Rows)
{
if (Convert.ToInt32(dta["parent_id"]) == parentID)
{
String key = dta["id"].ToString();
String text = dta["host_ip"].ToString();
TreeNode tn = new TreeNode();
tn.Name = dta["id"].ToString();
tn.Text = dta["host_ip"].ToString();
tn.ToolTipText = dta["description"].ToString();
parentNode.Add(tn);
TreeNodeCollection newParentNode = parentNode;
CreateTreeView(newParentNode, Convert.ToInt32(dta["id"]), mytab);
}
}
}
Calling code:
CreateTreeView(treeView1.Nodes, 0, dt);
If someone had with this problem here is an example:
void add_tooltiptext(DataTable mytab)
{
try
{
foreach (DataRow nodes in mytab.Rows)
{
TreeNode[] found = treeView1.Nodes.Find(nodes["id"].ToString(), true);
for (int i = 0; i < found.Length; i++)
{
treeView1.SelectedNode = found[i];
treeView1.SelectedNode.ToolTipText = nodes["description"].ToString();
}
}
}
catch
{ }
}
I need to remove elements in some xml files. How do I correctly ensure that I transverse through all childnodes to remove all element with a matching name. I have code such as:
string strFilename = #"D:\sample.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strFilename);
XmlNode parentNode;
parentNode = xmlDoc.DocumentElement;
foreach (XmlNode node1 in parentNode.ChildNodes)
{
foreach (XmlNode node2 in node1.ChildNodes)
{
if (node2.Name == "ElementNodeToDelete")
{
node2.ParentNode.RemoveChild(node2);
}
foreach (XmlNode node3 in node2.ChildNodes)
{
if (node3.Name == "ElementNodeToDelete")
{
node3.ParentNode.RemoveChild(node3);
}
foreach (XmlNode node4 in node3.ChildNodes)
{
if (node4.Name == "ElementNodeToDelete")
{
node4.ParentNode.RemoveChild(node4);
}
}
}
}
}
Is this a valid solution? How do I determine how many foreach loops to perform to ensure that all children are checked?
Thanks for your time in advance.
Recursion is your friend.
void DeleteNodes(XmlNode root, string deleteName)
{
foreach(XmlNode node in root.ChildNodes)
{
if (node.Name == deleteName)
{
root.RemoveChild(node);
}
else
{
DeleteNodes(node,deleteName);
}
}
}
I am trying to loop through an Xml file and display the value for account in a message.
XmlNodeList nodeList = testDoc.SelectNodes("/details/row/var");
foreach (XmlNode no in nodeList)
{
XmlNode node = testDoc.SelectSingleNode("/details/row/var[#name='account']");
test.actual = node.Attributes["value"].Value;
MessageBox.Show(test.account);
}
The message box is currently displaying the first record repeatidly, how can I get to the next record?
Thanks for your input in advance.
You are repeatedly assigning node with the same element from testDoc. It is not clear what test.account is (perhaps a mistype for test.actual)?
no is the variable which will iterate the contents of nodeList - I imagine you intended to use that.
EDIT following edit of OP
Now you've shown us what nodeList is, I suspect you want to do something like this instead :
XmlNodeList nodeList = testDoc.SelectNodes("/details/row/var[#name='account']");
foreach (XmlNode no in nodeList)
{
test.actual = no.Attributes["value"].Value;
...
XmlDocument doc = new XmlDocument();
doc.Load("d:\\test.xml");
XmlNodeList node = doc.GetElementsByTagName("w:r");
foreach (XmlNode xn in node)
{
try
{
if (xn["w:t"].InnerText != null)
{
if (xn["w:t"].InnerText == "#")
{
string placeHolder = xn["w:t"].InnerText;
foreach (XmlNode a in node)
{
if (a["w:t"].InnerText != "#")
{
string placeHolder1 = a["w:t"].InnerText;
}
}
}
}
}
catch (Exception e)
{
Console.Write(e);
}
}
Here is the sample for parent node value to get information of the child nodes.here i am using the ReportItems ParentNode and Print only image child nodes.
xmldoc.Load(rdlFile);
StringBuilder sb=new StringBuilder();
XmlNode node = xmldoc.GetElementsByTagName("ReportItems")[0];
XmlNodeList list = node.ChildNodes;
atributes=new string[node.ChildNodes.Count];
int l = 0;
for (int j = 0; j < node.ChildNodes.Count; j++)
{
if (list[j].Name == "Image")
{
XmlAttributeCollection att = list[j].Attributes;
atributes[l] = att[0].Value.ToUpper();
}
l++;
}
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (searchText.Text.ToUpper() == atributes[i])
{
XmlNodeList lastlist = node.ChildNodes;
XmlNodeList endlist = lastlist[i].ChildNodes;
for (int k = 0; k < endlist.Count; k++)
{
sb.Append(endlist[k].Name+" - "+ endlist[k].InnerText);
sb.Append("\n"+"\n");
}
}
}
let me know if you have doubt..
Try this,
XmlDocument xdoc = new XDocument();
xdoc.Load("*/File/*");
string xmlcontents = xdoc.InnerXml;
var xpath = "(/details/row/var[#name='account'])";
XmlNodeList lists = xdoc.DocumentElement.SelectNodes(xpath);
foreach (XmlNode _node in lists)
{
string _nodeValue = _node.InnerText;
MessageBox.Show(_nodeValue);
}
Try the following:
//Create an xml reader;
XmlDocument _xmlDocument = new XmlDocument();
_xmlDocument.Load(/*File Name here*/);
//Select the element with in the xml you wish to extract;
XmlNodeList _nodeList = _xmlDocument.SelectNodes("/details/row/var[#name='account']");
//Display the values in the node list to the screen;
foreach (XmlNode _node in _nodeList)
{
String _nodeValue = _node.InnerText.ToString();
MessageBox.Show(_nodeValue.ToString());
}
I'm not 100% sure, but you may need to use recursion. If not, it should just look like this:
XmlDocument doc = //etc..
foreach(XmlNode node in doc.ChildNodes)
{
if(node.Name == "account")
{
MessageBox.Show(node.Value);
}
}
You shouldn't spend time with reading the xml node by node. Try Deserialization: