How do I loop backwards from SiteMap.CurrentNode to SiteMap.RootNode - c#

I have a simple Sitemap like this from asp:SiteMapDataSource:
Page 1 > Page 2 > Page 3
I would like to create foreach loop in C# that generates it instead for using asp:SiteMapPath because I need to add some exceptions to it. Now I cannot figure out how do I loop backwards from SiteMap.CurrentNode to SiteMap.RootNode?

The property you are looking for is SiteMapNode.ParentNode
SiteMapNode currentNode = SiteMap.CurrentNode;
SiteMapNode rootNode = SiteMap.RootNode;
Stack<SiteMapNode> nodeStack = new Stack<SiteMapNode>();
while (currentNode != rootNode)
{
nodeStack.Push(currentNode);
currentNode = currentNode.ParentNode;
}
// If you want to include RootNode in your list
nodeStack.Push(rootNode);
SiteMapNode[] breadCrumbs = nodeStack.ToArray();

Related

XML Node Attribute returning as NULL when populated?

I have a XML Doc that I'm pulling out a specific Node and all of it's attributes. In debug mode I can see that I'm getting the specific Nodes and all of their attributes. However, when I try to get the attribute value it can't find it and returns a NULL value. I've done some searching and looked at some examples and from what I can tell I should be getting the value but I'm not and I don't see what I'm doing wrong.
I'm trying to get the StartTime value.
Here is the XML that is returned.
Here you can see in debug and with the Text Visualizer the value should be there.
The code I'm trying.
XmlNodeList nodes = xmlDoc.GetElementsByTagName("PlannedAbsences");
if (nodes != null && nodes.Count > 0)
{
foreach (XmlNode node in nodes)
{
if (node.Attributes != null)
{
var nameAttribute = node.Attributes["StartTime"];
if (nameAttribute != null)
{
//var startDate = nameAttribute.Value;
}
}
}
}
Using the XDocument class contained within the System.Xml.Linq namespace, grab the sub elements from the PlannedAbsences parent, then iterate over sub elements retrieving the value of the desired attribute.
var xmlDoc = XDocument.Load(#"path to xml file")
var absences = xmlDoc.Element("PlannedAbsences")?.Elements("Absence");
foreach (var item in absences)
{
var xElement = item.Attribute("StartTime").Value;
Console.WriteLine(xElement);
}

Select a child node in XML with specific name using C#

I am trying to find a child element with tag name Reason.
I have XML doc that is basically contains bunch of elements with Entity name.
Reason tag is somewhere inside of Entity(along with other elements).
void IParseResponse.ParseResponseData(XmlDocument responseDocument)
{
List<string> reasons = new List<string>();
var reasonValue = "";
var entityList = responseDocument.GetElementsByTagName("Entity");
if (entityList != null)
{
foreach (XmlNode reason in entityList)
{
reasonValue = //look into current Entity element, find Reason in it and get it's inner text.
reasons.Add(reasonValue);
}
}
}
This is location of Reason element.
<Entity>
<WatchList>
<Match ID="1">
<MatchDetails>
<Reason>
Does anybody have experience with this?
Here's how you can get all the Reason elements.
var xml = "<Entity> <WatchList><Match ID=\"1\"><MatchDetails><Reason>asdasd</Reason></MatchDetails></Match></WatchList></Entity>";
var x = XDocument.Parse(xml);
var reasons = x.Descendants("Reason").ToList();
foreach (var reason in reasons)
{
Console.WriteLine(reason.Value);
}
If you give us a more complete example of your XML I can improve the answer.
Edit:
If you want to use XmlDocument instead you could do this:
XmlNodeList nodes = responseDocument.GetElementsByTagName("Reason");
for (int i = 0; i < nodes.Count; i++)
{
Console.WriteLine(nodes[i].InnerText);
}

C# HtmlDocument Extract Classes

I am writing some code to loop through every element in a HTML page and extract all ID and Classes.
My current code is able to extract the ID's but I can't see a way to get the classes, does anybody know where I can access these?
private void ParseElements()
{
// GET: Document from Browser
HtmlDocument ThisDocument = Browser.Document;
// DECLARE: List of IDs
List<string> ListIdentifiers = new List<string>();
// LOOP: Through Each Element
for (int LoopA = 0; LoopA < ThisDocument.All.Count; LoopA += 1)
{
// DETERMINE: Whether ID Exists in Element
if (ThisDocument.All[LoopA].Id != null)
{
// ADD: Identifier to List
ListIdentifiers.Add(ThisDocument.All[LoopA].Id);
}
}
}
You could get the inner HTML of each node and use a regular expression to get the class. Or you could try HTML Agility pack.
Something like...
HtmlAgilityPack.HtmlDocument AgilePack = new HtmlAgilityPack.HtmlDocument();
AgilePack.LoadHtml(ThisDocument.Body.OuterHtml);
HtmlNodeCollection Nodes = AgilePack.DocumentNode.SelectNodes(#"//*");
foreach (HtmlAgilityPack.HtmlNode Node in Nodes)
{
if (Node.Attributes["class"] != null)
MessageBox.Show(Node.Attributes["class"].Value);
}

How to delete a node if it has no parent node

I'm using the HTML agility pack to clean up input to a WYSIWYG. This might not be the best way to do this but I'm working with developers who explode on contact with regex so it will have to suffice.
My WYSIWYG content looks something like this (for example):
<p></p>
<p></p>
<p><span><input id="textbox" type="text" /></span></p>
I need to strip the empty paragraph tags. Here's how I'm doing it at the moment:
HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//p");
if (nodes == null)
return;
foreach (HtmlNode node in nodes)
{
node.InnerHtml = node.InnerHtml.Trim();
if (node.InnerHtml == string.Empty)
node.ParentNode.RemoveChild(node);
}
However, because the HTML is not a complete document the paragraph tags do not have a parent node and RemoveChild will therefore fail since ParentNode is null.
I can't find another way to remove tag though, can anyone point me at an alternate method?
Technically, first-level elements are children of the document root, so the following code should work:
if (node.InnerHtml == String.Empty) {
HtmlNode parent = node.ParentNode;
if (parent == null) {
parent = doc.DocumentNode;
}
parent.RemoveChild(node);
}
You want to remove from the collection, right?
HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//p");
if (nodes == null)
return;
for (int i = 0; i < nodes.Count - 1; i++)
{
nodes[i].InnerHtml = nodes[i].InnerHtml.Trim();
if (nodes[i].InnerHtml == string.Empty)
nodes.Remove(i);
}

How to clean up "TreeNode"s with same Text property in a TreeView?

I have a TreeView which will be populated with some Nodes. The problem is, this nodes can have different Tag and Name property but some of them can have the same Text property.
I want to have only one node from each of above nodes, so the TreeView will have unique nodes by Text.
I am trying to make a list of all nodes then filter them, then add the new List to the TreeView. Here is my approach, and I commented the line which does not compile.
//Remove Duplicated Nodes
List<TreeNode> oldPinGrpNodes = new List<TreeNode>();
List<TreeNode> newPinGrpNodes = new List<TreeNode>();
TreeNode tempNode;
foreach (TreeNode node in tvPinGroups.Nodes)
{
oldPinGrpNodes.Add(node);
}
foreach (TreeNode node in oldPinGrpNodes)
{
if (newPinGrpNodes.Contains(node.Text)) continue; //this does not compile!
//How to do a check in the IF statement above?
//Continue with adding the unique pins to the newList
}
Or if you have any better idea please let me know!
have you tried the following Linq query, instead of your check?
if (newPinGrpNodes.Any(n => n.Text == node.Text)) continue;
if(newPinGrpNodes.Any(n => n.Text==node.Text)) continue;
foreach (TreeNode node in oldPinGrpNodes)
{
if ( from m in newPinGrpNodesLookup where m.text=node.Text select m).first ==null)
continue;
}
Try this. I'm using ToLookup extension method in System.Linq:
//Remove Duplicated Nodes
List<TreeNode> oldPinGrpNodes = new List<TreeNode>();
Dictionary<string, TreeNode> newPinGrpNodes = new Dictionary<string, TreeNode>();
TreeNode tempNode;
foreach (TreeNode node in tvPinGroups.Nodes)
{
oldPinGrpNodes.Add(node);
}
foreach (TreeNode node in oldPinGrpNodes)
{
if (newPinGrpNodes.ContainsKey(node.Text)) continue; //this does not compile!
//How to do a check in the IF statement above?
//Continue with adding the unique pins to the newList
// do something like
newPinGrpNodes.Add(node.Text, node);
}
As for your compilation error, newPinGrpNodes - collection of type TreeNode and you try to search string there.
UPDATE:
For performance, it's better to use Dictionary for searching items: Dictionary<string, TreeNode> instead of List<TreeNode>.

Categories

Resources