10. LINQ to XML || C# 10 Flashcards
What is a Document Object Model (aka DOM) ?
The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the document as a structured tree of objects that can be manipulated with code. The DOM is not specific to C#, but is used in many programming languages to provide a way to interact with web pages and other structured documents.
The DOM provides a way to access and manipulate the content and structure of a document using a set of standard methods and properties. This includes adding and removing elements, updating attribute values, and changing the contents of text nodes. The DOM also provides a way to handle events that occur within the document, such as user clicks and changes to form elements.
Overall, the DOM is a powerful tool for working with structured documents in C#, and is a key part of many web development projects.
What are the differences between DOM and X-DOM if for example we would want to use LINQ on it?
Although we could use LINQ to query a DOM created of the older W3C-compliant types, this would be frustrating and limiting. The distinguishing feature of the X-DOM is that it’s LINQ-friendly, meaning:
* It has methods that emit useful IEnumerable sequences upon which you can query;
* Its constructors are designed such that you can build an X-DOM tree through a LINQ projection;
Describe the core of X-DOM types
- XObject is the abstract base class for all XML content. It defines a link to the Parent element in the containership tree as well as an optiona XDocument;
-
XNode is the base class for most XML content excluding attributes. The distinguishing feature of XNode is that it can sit in an ordered collection of mixed-type XNodes. Although an XNode can access its parent XElement, it has no concept of child nodes: this is a job of its subclass XContainer.
<data>
// Parent element ‘data’
` Hello World// XText node "Hello World"
<subelement1></subelement1>// XElement node
<!-- comment -->// XComment node
<subelement2></subelement2>// XElement node
</data>` - XContainer defines members for dealing with children and is the abstract base class for XElement and XDocument.
- XElement introduces members for managing attributes - as well as a Name and Value. In the case of an element having a single text XText child node, the Value property on XElement encapsulates this child’s content for both get and set operations, cutting unnecessary navigation.
- XDocument represents the root of an XML tree. More precisely, it wraps the root XElement, adding an XDeclaration, processing instructions, and other root-level “fluff”. Unlike with the W3C DOM, its use is optional: you an load, manipulate, and save an X-DOM without ever creating an XDocument. The nonreliance on XDocument also means that you can efficiently and easily move a node subtree to another X-DOM hierarchy.
Both XElement and XDocument provide static Load and Parse methods. What do they do and what are the differences between them?
Both Load and Parse methods are used to build an X-DOM tree from an existing source:
* Load builds an X-DOM from a file, URI, Stream, TextReader or XmlReader;
* Parse builds an X-DOM from a string;
Examples:
LOAD:
1. XElement fromFile = XElement.Load(@"e:\media\somefile.xml");
PARSE:
2. XElement config = XElement.Parse(
@"<configuration>
<client enabled='true'>
` <timeout>30</timeout>
</client>
</configuration>”);`
How can we manually construct an X-DOM tree from scratch, that would look like this:
~~~
<customer>
<firstName>Joe</firstName>
<lastName>Bloggs
<!-- nice name-->
</lastName>
</customer>
~~~
Describe two methods
XElement customer = new XElement("customer"); customer.Add(new XAttribute("id", 123);) customer.Add(new XElement("firstName", "Joe")); XElement lastName = new XElement("lastName", "Bloggs"); lastName.Add(new XComment("nice name")); customer.Add(lastName);
OR by functional construction:
~~~
XElement customer =
new XElement(“customer”, new XAttribute(“id”, 123)),
new XElement (“firstName”, “Joe”),
new XElement(“lastName”, “Bloggs”,
new XComment(“nice name”)
)
);
~~~
How many child objects can be specified when creating XElement or adding something to it? Why is that?
The constructors for XElement (and XDocument) are overloaded to accept a params object array:public XElement (XName name, params object[] content)
The same holds true for the Add method in XContainer:public void Add (params object[] content)
Hence, you can specify any number of child objects of any type when building or appeding an X-DOM. This works because anything counts as legal content.
What happens when we call ToString()
to XDOM object?
Before calling ToString()
on an arbitrary type, XContainer first tests whether it is one of the following types: float, double, decimal, bool, DateTime, DateTimeOffset, TimeSpan.
If so, it calls an appropriate typed ToString method on the XmlConverter helper class instead of calling ToString on the object itself. This ensures that the data is round-trippable and compliant with standard XML formatting rules
What are the return types for XNode or XContainer methods?
These methods return either a single value or a sequence that implements IEnumerable<T>
- upon which you are then expected to execute a LINQ query (or enumerate with foreach)
What the result would be if we would call Nodes()
on this “bench” object?
If then we would printout (by ToString()
) the result in foreach block:
How Nodes()
method is different from Elements()
method in X-DOM? Lets consider we would call it on this object:
If we would loop through the items that each method returns:
* Nodes()
would return sequence entire elements. After calling ToString()
on it we would get <toolbox/><handtool>Hammer</handtool><handtool>Rasp</handtool></toolbox>
* Elements()
would return object with Name and Value parameters like e.Name (“toolbox”) and e.Value (“HammerRasp”)
How can we rewrite (refactor) this X-DOM query:
var result = bench.Elements().Where(w => w.Name == “toolbox” )
The same result would be retrieved by calling bench.Elements(“toolbox”)
What is the difference between calling Elements()
and Element()
on a X-DOM object?
-
Elements()
return a sequence of child nodes of type XElement -
Element()
however is equivalent to calling Elements() and then applying LINQ’s FirstOrDefault query operator with a name-matching predicate. Element returns null if the requested element doesn’t exist.
How we can traverse nodes in X-DOM ? Why is that?
HOW: We can traverse nodes with PreviousNode() and NextNode() methods.
WHY: Internally, nodes are stored in a singly linked list, so the way we are can go through them is taken from there as well.
BONUS: Also, since this XNode internally uses singly linked list, that means that PreviousNode() is not performant - In a singly linked list, each node only has a reference to its next node in the list. To access the previous node, one needs to start at the head of the list and iterate through the list until reaching the desired node. This can be a slow operation, especially if the list is long and the desired node is far from the head.
Name 5 ways how can you update elements and attributes in X-DOM
- Call SetValue or reassign the Value property;
- Call SetElement or SetAttributeValue;
- Call one of the RemoveXXX methods;
- Call one of the AddXXX or ReplaceXXX methods, specifying fresh content;
Name the difference between Add() and AddFirst() methods in X-DOM
Add() appends a child node to an element or document. AddFirst() does the same thing, but instead inserts at the beginning of the collection rather than the end