Indexed access to XElement‘s child nodes - c#

I am parsing an XML document using LINQ to XML and XDocument. Is there a way for a XElement/XContainer to get a child node by the index (in document order)? So that I can get the nth node of the element?
I know I can probably do that by getting all the child nodes of that element and converting that IEnumerable to a List, but that already sounds like it would add a highly redundant overhead (as I am only interested in a single child node).
Is there something I missed in the documentation?

No, there is no indexed access to a child element using XElement or XContainer. If you want indexed access, you have two options.
The first is to call the Elements method on XContainer (which returns an IEnumerable<T> of XElement instances in document order) and then use the Skip extension method to skip over the elements to reach the particular child.
If you want to access the child elements often by index, then you should place them in a IList<T> (which has indexed access), which is easy enough with the ToList extension method:
IList<XElement> indexedElements = element.Elements().ToList();

what about Skip(n).Take(1) operators

Maybe Take(topN) LINQ directive can help?
I'm making assumption based on some SQL related experience - you cannot get the row directly, but can take top n elements.
This can help if your list is huge and you don't encount last elements.

Related

How to get all elements in an XDocument whose value matches some criterion

I need to get hold of all the elements in an XDocument, regardless of name, whose value matches some criterion.
The 'matching a criterion' part isn't the problem - the problem is how to get a collection of all the XElements in an XDocument, in other words to flatten it into a 'list' of XElements, without specifying the element names.
myXDocument.Descendants().Where(el => IsAMatch(el.Value))
only seems to return the first level, but the elements in question are nested a variety of levels deep and have a variety of names over which I have no control (and to be honest, no interest either. I just want to find them).
I could do it recursively, walking the tree and adding every matching element to a list, but it doesn't seem very elegant (and is probably quite slow).
How can do I do this more elegantly?
TIA
I can see what is happening now - Descendants() is indeed returning all the elements, but nested elements are returned within their parent elements AND in their own right, which I hadn't spotted. IsAMatch(...) needs to constrain itself to the element's immediate value, ignoring the nested (child) elements.

How to get all the top level htmlelements from C# WebBrowser?

I want to show the DOM as it is on the web browser with all comments and html, head, body, etc.. preserve its structure. Currently, I can only start from node html. Document.All didnt help.
The only way I can see is webBrowser1.Document.Body but I would miss the commentss, head etc.. Then if I go with Document.All then that gives me all the nodes.
I think the only choice with the WebBrowser control to get what you want is to use Document.All. Although this gives all elements not just top-level, each element has a .Parent element property so you can loop through them (or use Linq) and get only the ones that have <body> or <head> as the parent element.
Try using HTMLAgilityPack, it support Xpath so you can get any node as you want.
As suggested by hienvd_csuit, I think HTML Agility Pack is your best option. If you still want to use the WebBrowser, a possible solution is to access the unmanaged DOM directly, using dynamic (requires .NET 4+). For instance you can do something like this:
dynamic dom = wb.Document.DomDocument;
foreach (dynamic node in dom.childNodes)
{
Console.WriteLine ("{0} - {1} - {2}", node.nodeType, node.nodeName, node.nodeValue);
}
Of course, you need to know the structure of the DOM, since intellisense doesn't work on dynamic objects; you can find some information about it here.
You should be able to query (there is a property somewhere) if a particular item has a child node or not, also, you can query if it is a parent node or if a particular item has a parent or not, and if it does, discard, and you can keep querying for parent such as item.parent.parent (pls check intellisense for exact object/property names) and if it returns nothing, it means there is only one parent (assuming item.parent doesnt return nothing), and you can organize how many levels deep the nodes can/must be. So based on the child or parent checking method (or both) you can choose to either include it in your collection or discard it.
Of course, you might get many "P" tags or DIV/SPAN tag's as your top level nodes/items. So, i'm assuming there is a chance you will not want these, so feel free to discard them and query their children.

Deserialized xml - check if has child nodes without knowing specific type

I have deserialized an xml file into a C# object and have an "object" containing a specific node I have selected from this file.
I need to check if this node has child nodes. I do not know the specific type of the object at any given time.
At the moment I am just re-serializing the object into a string, and loading it into an XmlDocument before checking the HasChildNodes property, however when I have thousands of nodes to check this is extremely resource intensive and slow.
Can anyone think of a better way I can check if the object I have contains child nodes?
Many thanks :)
try using Linq2xml, it has a class called XElement (or XDocument) which are much easier to use then the XmlDocument.
something like this:
XElement x = XElement.Load("myfile.xml");
if (x.Nodes.Count() > 0)
{
// do whatever
}
much less code, much more slick, very readable.
if you have the xml already as a string, you can replace the Load with the Parse function.
I guess you could reverse the process (looking at all public members/properties that aren't marked [XmlIgnore], aren't null, and don't have a public bool ShouldSerialize*() that returns false or any of the other patterns), but this seems a lot of work...

.NET tree object model

I like Microsoft's Windows Forms tree-view object model. It has the tree, nodes, children collection, parent, prev, next (sibling), etc. and search function. However I'm looking for the same object model with no UI - simply tree object model.
Does C# have this kind of model or do I have to implement it myself?
C# is a programming language. It does not have object models.
You may be asking whether the .NET Framework has a built-in "tree" class. It does not. You can build your own using the generic collection classes like LinkedList<T> and List<T>.
You could always use XML and the XML namespaces. It's got all the things you requested. Start with and XMLDocument and keep added XMLNodes and adding XMLNodes to the XMLNodes for children. Then you can use xpath queries to retrieve nodes.
An XmlDocument object is the closest match I can think of to your requirements. It supports parent, child, previous, next, sibling, etc. You can also use XPath to query the tree and return a specific node or sets of nodes. Also, because it's Xml you can easily import and export the data to/from a text file.
I suggest you read about binary trees on MSDN. It will teach you how to model tree data structures in code.
Good luck.

Can I find Logical Children by Type

I know i can use LogicalTreeHelper class to find children node for every element searching it by name. But is there a possibility to find a child node by Type? For example, what if i would like to find a ListBox element in my Window without knowing its Name property??
I don't think that there is a built in way of doing this. Probably the best approach would be to recursively call LogicalTreeHelper.GetChildren() until a child control of the specified type is found.
Note that descending the Logical tree cleanly is actually a little tricky, here's a nice article on the intricacies of both the visual and logical trees.
I don't think any helper code exists to do this for you so implementing a recursive walk over the tree is required.

Categories

Resources