Converting Xdocument to Xmldocument and Vice Versa

Converting XDocument to XmlDocument and vice versa

You can use the built in xDocument.CreateReader() and an XmlNodeReader to convert back and forth.

Putting that into an Extension method to make it easier to work with.

using System;
using System.Xml;
using System.Xml.Linq;

namespace MyTest
{
internal class Program
{
private static void Main(string[] args)
{

var xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<Root><Child>Test</Child></Root>");

var xDocument = xmlDocument.ToXDocument();
var newXmlDocument = xDocument.ToXmlDocument();
Console.ReadLine();
}
}

public static class DocumentExtensions
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using(var xmlReader = xDocument.CreateReader())
{
xmlDocument.Load(xmlReader);
}
return xmlDocument;
}

public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}
}

Sources:

  • http://msdn.microsoft.com/en-us/library/bb356384.aspx
  • http://geekswithblogs.net/aspringer/archive/2009/07/01/xdocument-extension.aspx

XDocument to XElement

XDocument to XmlDocument:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xdoc.CreateReader());

XmlDocument to XDocument

XDocument xDoc = XDocument.Load(new XmlNodeReader(xmlDoc));

To get the root element from the XDocument you use xDoc.Root

XDocument or XmlDocument

If you're using .NET version 3.0 or lower, you have to use XmlDocument aka the classic DOM API. Likewise you'll find there are some other APIs which will expect this.

If you get the choice, however, I would thoroughly recommend using XDocument aka LINQ to XML. It's much simpler to create documents and process them. For example, it's the difference between:

XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("root");
root.SetAttribute("name", "value");
XmlElement child = doc.CreateElement("child");
child.InnerText = "text node";
root.AppendChild(child);
doc.AppendChild(root);

and

XDocument doc = new XDocument(
new XElement("root",
new XAttribute("name", "value"),
new XElement("child", "text node")));

Namespaces are pretty easy to work with in LINQ to XML, unlike any other XML API I've ever seen:

XNamespace ns = "http://somewhere.com";
XElement element = new XElement(ns + "elementName");
// etc

LINQ to XML also works really well with LINQ - its construction model allows you to build elements with sequences of sub-elements really easily:

// Customers is a List<Customer>
XElement customersElement = new XElement("customers",
customers.Select(c => new XElement("customer",
new XAttribute("name", c.Name),
new XAttribute("lastSeen", c.LastOrder)
new XElement("address",
new XAttribute("town", c.Town),
new XAttribute("firstline", c.Address1),
// etc
));

It's all a lot more declarative, which fits in with the general LINQ style.

Now as Brannon mentioned, these are in-memory APIs rather than streaming ones (although XStreamingElement supports lazy output). XmlReader and XmlWriter are the normal ways of streaming XML in .NET, but you can mix all the APIs to some extent. For example, you can stream a large document but use LINQ to XML by positioning an XmlReader at the start of an element, reading an XElement from it and processing it, then moving on to the next element etc. There are various blog posts about this technique, here's one I found with a quick search.

Obtaining XmlElement from XDocument

Use this:

var newDoc = new XmlDocument();
newDoc.LoadXml(doc.ToString());
3rdPartyFunction(newDoc);

Unable to parse webpage by converting to XmlDocument

While a boolean attribute like async is a valid HTML attribute, it is not a valid XML attribute (read more). So it is correct, that the conversion to XML fails.

You get different results, because the conversion through a type cast to [xml] really tries to parse the content to XML, while ConvertTo-Xml does something completely different. Look at the result of the following command:

('<script async src = "test.js"></script>' | ConvertTo-Xml).OuterXml

Output:

<?xml version="1.0" encoding="utf-8"?><Objects><Object Type="System.String"><script async src = "test.js"></script></Object></Objects>

The pure string is converted into the inner text of an XML element. I guess, that's not what you want.

ConvertTo-Xml is designed to:

create an XML-based representation of one or more more .NET objects.

It does not convert a string containing XML into XML.


Not every HTML page consists of pure XML. So you can not rely on parsing every website to XML. There is XHTML though, which is valid XML. In XHTML, the script tag should look like this:

<script async="async" src = "test.js"></script>

The async attribute could have any other value, to be precise, as long as it has a value (read more).

In your case, I recommend to parse the website to HTML. Invoke-WebRequest does that already for you:

$html = ( Invoke-WebRequest https://www.pinvoke.net/default.aspx/advapi32/CreateProcessAsUser.html ).ParsedHtml

Copying part of an xml document to another document using Xdocument

Here is an example of copying data "xml" from one document to another.With selection of personalized node

First you need convert Xdocument to XmlDocument:

using System;
using System.Xml;
using System.Xml.Linq;

namespace MyTest
{
internal class Program
{
private static void Main(string[] args)
{

var xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<Root><Child>Test</Child></Root>");

var xDocument = xmlDocument.ToXDocument();
var newXmlDocument = xDocument.ToXmlDocument();
Console.ReadLine();
}
}

public static class DocumentExtensions
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using(var xmlReader = xDocument.CreateReader())
{
xmlDocument.Load(xmlReader);
}
return xmlDocument;
}

public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}
}

And now simplified copy with XmlDocument

    XmlDocument doc1 = new XmlDocument();
doc1.LoadXml(@"<Hello>
<World>Test</World>
</Hello>");

XmlDocument doc2 = new XmlDocument();
doc2.LoadXml(@"<Hello>
</Hello>");

XmlNode copiedNode = doc2.ImportNode(doc1.SelectSingleNode("/Hello/World"), true);
doc2.DocumentElement.AppendChild(copiedNode);

more information here:

  1. http://blog.project-sierra.de/archives/1050
  2. Copy Xml element to another document in C#
  3. Converting XDocument to XmlDocument and vice versa

I hope this help you.



Related Topics



Leave a reply



Submit