10. LINQ to XML || C# 10 Flashcards

1
Q

What is a Document Object Model (aka DOM) ?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What are the differences between DOM and X-DOM if for example we would want to use LINQ on it?

A

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;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Describe the core of X-DOM types

A
  • 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.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Both XElement and XDocument provide static Load and Parse methods. What do they do and what are the differences between them?

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

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

A
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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How many child objects can be specified when creating XElement or adding something to it? Why is that?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What happens when we call ToString() to XDOM object?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What are the return types for XNode or XContainer methods?

A

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)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What the result would be if we would call Nodes() on this “bench” object?

A

If then we would printout (by ToString()) the result in foreach block:

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

How Nodes() method is different from Elements() method in X-DOM? Lets consider we would call it on this object:

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How can we rewrite (refactor) this X-DOM query:

var result = bench.Elements().Where(w => w.Name == “toolbox” )

A

The same result would be retrieved by calling bench.Elements(“toolbox”)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the difference between calling Elements() and Element() on a X-DOM object?

A
  • 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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

How we can traverse nodes in X-DOM ? Why is that?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Name 5 ways how can you update elements and attributes in X-DOM

A
  1. Call SetValue or reassign the Value property;
  2. Call SetElement or SetAttributeValue;
  3. Call one of the RemoveXXX methods;
  4. Call one of the AddXXX or ReplaceXXX methods, specifying fresh content;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Name the difference between Add() and AddFirst() methods in X-DOM

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

There are two ways to assign a value to an element in X-DOM: call SetValue() or assign a Value property. Why would I want to choose one over another?

A

Although they both are setting a new value to the element SetValue() method is more flexible because it accepts not just strings but other simple data type too

17
Q

What happens when we pass a value into XElement or XAttribute’s constructor?

A

An automatic conversion takes place for non-string types - it requires the use of XmlConvert for an XML-complient results. This ensures that DateTimes are correctly formatted; true is written ib lowercase, and double.NegativeInfinity is written as “-INF”.

18
Q

Which object in X-DOM is created automatically on doc.Save() and does not appear in document’s Nodes collection?

A

An XDeclaration is not an XNode and does not appear in the document’s Nodes collection - unlike comments, processing instructions and the root element. Instead, it’s assigned to a dedicated property called Declaration.

19
Q

What does the XML declaration do? And when is it created?

A

An XML declaration ensures that the file will be correctly parsed and understood by a reader.
XML declaration is created:
• calling Save() with a filename always writes a declaration;
• calling Save with an XmlWriter writes a declaration unless the XmlWriter is instructed otherwise;
• to ToString() method never emits an XML declaration

20
Q

What is an XDeclaration? Whats the purpose for it?

A

This is XML declaration:
<?xml version=“1.0” encoding=“utf-8” standalone=“yes”?>
The purpose of an XDeclaration is instead to hint the XML serialization in two ways:
1. What text encoding to use;
2. What to put in XML declaration’s encoding and standalone attributes (should a declaration be written);

21
Q

Why the ToString() method doesn’t emit the XML declaration?

A

First let’s begin with the fact the ToString() method applies utf-16 encoding even though we potencially would have requested any other encoding (like utf-8).
Because we’re writting to a string and not a file or stream, it’s impossible to apply any encoding other than UtF-16 - the format in which strings are internally stored.
This also explains why the ToString() method doesnt emit an XML declaration. Imagine that instead of calling Save, you did the following to write an XDocument to a file:
File.WriteAllText(“data.xml”, doc.ToString());
As it stands, data.xml would lack an XML declaration, making it incomplete but still parsable (you can infer the text encoding). But if ToString() emitted an XML declaration, data.xml would actually contain an incorrect declaration (encoding=“utf-16”), which might prevent it from being read at all because WriteAllText encodes using UTF-8

22
Q

How can we define a namespace in X-DOM?

A

There are wo ways of doing that. The first one is to use the xmlns attribute:
<customer xmlns=“Inga.Mokosi.CSharp”/>
xmlns is a special reserved attribute. When used in manner, it performs two functions:
1. It specifies a namespace for the element in question;
2. It specifies a default namespace for all descendant elements;
The other way to specify a namespace is with a prefix. A prefix is an alias that you assign to a namespace to save typing. There are two steps of using a prefix - defining the prefix and the using it. You can do both together:
<nut: customer xlmns:nut=“Inga.Mokosi.CSharp”/>

23
Q

How to declare a namespace while creating a new XElement() ?

A

Like so:
new XElement(“{newNamespace}myObject, “This is content”);
This yields the resulting XML:
<myObject xmlns=“newNamespace” >This is content</ myObject>

24
Q

If we add an annotation to XDOM like so:
~~~
XElement e = new XElement(“test”);
e.AddAnnotation(new CustomData {Message = “Hello”});
~~~
How can we retrieve all annotations by the type?

A

e.Annotations<CustomData>() will give us the list of all annotations that are of type CustomData

25
Q

Can we somehow combine XDOM and SQL queries together?

A

Yes we can:
~~~
var customers =
new XElement (“customers”,
from c in dbContext.Customers.AsEnumerable()
select
new XElement (“customer”, new XAttribute(“id”, c.ID),
new XElement (“name”, c.Name),
new XElement(“buys”, c.Purchaces.Count)
~~~

The SQL part is of type IEnumerable<XElement>

26
Q

What can we use instead of XElement to improve memory efficiency?

A

We can use XStreamingElement fo the purposes of saving the element. We can do it like so:
~~~
var customers =
new XStreamingElement(“customers”,
from c in dbContext.Customers
select
new XStreamingElement(“customer”, new XAttribute (“id”, x.ID),
new XElement(“name”, c.Name),
new XElement(“buys”, c.Purchaces.Count)
```

27
Q

What are the differences between XElement and XStreamingElement?

A

The queries passed into XStreamingElement’s constructor are not enumerated until you call Save, ToString, or WriteTo on the element; this prevents loading the whole X-DOM into memory at once. The flipside is that the queries are reevaluated if you need to re-Save. Also, you cannot traverse an XStreamingElement’s child content - it does not expose methods such as Elements or Atributes.
XStreamingElement is not based on XObject - or any other class - because it has such a limited set of members. THe only members it has, besides Save, ToString and WriteTo are the following:
* An Add method, which accepts content like the constructor.
* A Name property