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.
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 or XmlDocument to JSON with C#
Use the method call
JsonConvert.SerializeXNode(x, Formatting.None, true);
this will omit the root node and should create what you expect.
How to change from XDocument to XMLDocument Code?
A basic example of this would be:
List<string> valueNames = new List<string>();
List<string> headingNames = new List<string>();
XmlDocument doc = new XmlDocument();
doc.Load("data.xml");
for (int r = 0; r < doc.ChildNodes.Count; r++)
{
var currentNode = doc.ChildNodes.Item(r);
if (currentNode.Name.Equals("ROOT"))
{
var columnsNode = currentNode.FirstChild;
for (int i = 0; i < columnsNode.ChildNodes.Count; i++)
{
XmlNode child = columnsNode.ChildNodes.Item(i);
for (int j = 0; j < child.Attributes.Count; j++)
{
var attribute = child.Attributes.Item(j);
if (attribute.Name.Equals("XPath"))
{
headingNames.Add(attribute.Value);
}
else if (attribute.Name.Equals("Name"))
{
valueNames.Add(attribute.Value);
}
}
}
}
}
Some explanation:
Your example XML has no XML Declaration, so we can get the Root Element simply be accessing theFirstChild
property.After Edit: Your example XML has now a XML Declaration, but the pattern is the same. For-Loop and accessing Child Elements per Indexer of this loop.
The 'Columns' Element can be reached the same way.
On the 'Columns' Element we for-loop through all Child Nodes and using the indexer (i) of our loop to get the corresponding element. Why? Because it's an
XmlNodeList
Object.With our
XmlNode child
we do the same, but this time not with Child Nodes. Instead we loop through the Attribute Nodes and looking for the correct name.
Convert XMLDocument to XDocument ,getting names spaces Modifing from xsi to p1
You need to explicitly add the xsi namespace declaration manually at the beginning of your element.
Nodes are processed in document order and the namespace declaration appears later after it is first used. It doesn't know to use xsi
for the prefix until it's too late.
var doc = new XmlDocument();
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));
var root = (XmlElement)doc.AppendChild(doc.CreateElement("BMECAT"));
var xsi = "http://www.w3.org/2001/XMLSchema-instance";
root.SetAttribute("xmlns:xsi", xsi); //set the namespace now
root.SetAttribute("schemaLocation", xsi, "http://www.adlnet.org/xsd/adlcp_v1p3");
root.SetAttribute("version", "2005");
Related Topics
Why Is It Important to Override Gethashcode When Equals Method Is Overridden
What Does the [Flags] Enum Attribute Mean in C#
Sending Email Through Gmail Smtp Server With C#
How to Pass Data (And References) Between Scenes in Unity
Implementing Inotifypropertychanged - Does a Better Way Exist
How to Implement Custom Jsonconverter in Json.Net
Why Not Inherit from List≪T≫
Converting a String to Datetime
C# Variance Problem: Assigning List≪Derived≫ as List≪Base≫
C# Compiler Error: "Not All Code Paths Return a Value"
How to Use Linq to Select Object With Minimum or Maximum Property Value
How to Implement Ixmlserializable
How to Cancel Task Await After a Timeout Period
An Existing Connection Was Forcibly Closed by the Remote Host