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:
- http://blog.project-sierra.de/archives/1050
- Copy Xml element to another document in C#
- Converting XDocument to XmlDocument and vice versa
I hope this help you.
Related Topics
How to Get the HTML Output of a Usercontrol in .Net (C#)
Handling Decimal Values in Newtonsoft.JSON
C# Webbrowser Control -- Get Document Elements After Ajax
Import a Public Key from Somewhere Else to Cngkey
Xamarin iOS Memory Leaks Everywhere
How to Add a Custom View to a Xib File Defined View in Monotouch
Style Bundling Not Working After Iis Deployment (MVC 4)
Load CSS Dynamically in ASP.NET
Dynamically Setting CSS Values Using ASP.NET
How to Display Formatted Code in Webpage
Bundling Not Working in MVC5 When I Turn on Release Mode
Why Aren't Variables Declared in "Try" in Scope in "Catch" or "Finally"
What Are Checked Exceptions in Java/C#
How to Request Administrator Permissions When the Program Starts
How to Convert an Object to a Byte Array in C#
In C#, What Happens When You Call an Extension Method on a Null Object