.NET: XDocument missing XDeclaration? [duplicate] - c#

Is there any way to have an XDocument print the xml version when using the ToString method? Have it output something like this:
<?xml version="1.0"?>
<!DOCTYPE ELMResponse [
]>
<Response>
<Error> ...
I have the following:
var xdoc = new XDocument(new XDocumentType("Response", null, null, "\n"), ...
which will print this which is fine, but it is missing the "<?xml version" as stated above.
<!DOCTYPE ELMResponse [
]>
<Response>
<Error> ...
I know that you can do this by outputting it manually my self. Just wanted to know if it was possible by using XDocument.

By using XDeclaration. This will add the declaration.
But with ToString() you will not get the desired output.
You need to use XDocument.Save() with one of his methods.
Full sample:
var doc = new XDocument(
new XDeclaration("1.0", "utf-16", "yes"),
new XElement("blah", "blih"));
var wr = new StringWriter();
doc.Save(wr);
Console.Write(wr.ToString());

This is by far the best way and most managable:
var xdoc = new XDocument(new XElement("Root", new XElement("Child", "台北 Táiběi.")));
string mystring;
using(var sw = new MemoryStream())
{
using(var strw = new StreamWriter(sw, System.Text.UTF8Encoding.UTF8))
{
xdoc.Save(strw);
mystring = System.Text.UTF8Encoding.UTF8.GetString(sw.ToArray());
}
}
and i say that just because you can change encoding to anything by changing .UTF8 to .Unicode or .UTF32

Late answer to an old question, but I shall try to provide more details than the other answers.
The thing you ask about, is called an XML declaration.
First of all, the XDocument has a property Declaration of type XDeclaration for this. You can either user another overload of the XDocument constructor:
var xdoc = new XDocument(
new XDeclaration("1.0", null, null), // <--- here
new XDocumentType("Response", null, null, "\n"), ...
);
or set the property later:
xdoc.Declaration = new XDeclaration("1.0", null, null);
But depending on how you save or write your XDocument later, the declaration (or parts of it) may be ignored. More on that later.
The XML declaration can have a number of appearances. Here are some valid examples:
<?xml version="1.0"?> new XDeclaration("1.0", null, null)
<?xml version="1.1"?> new XDeclaration("1.1", null, null)
<?xml version="1.0" encoding="us-ascii"?> new XDeclaration("1.0", "us-ascii", null)
<?xml version="1.0" encoding="utf-8"?> new XDeclaration("1.0", "utf-8", null)
<?xml version="1.0" encoding="utf-16"?> new XDeclaration("1.0", "utf-16", null)
<?xml version="1.0" encoding="utf-8" standalone="no"?> new XDeclaration("1.0", "utf-8", "no")
<?xml version="1.0" encoding="utf-8" standalone="yes"?> new XDeclaration("1.0", "utf-8", "yes")
<?xml version="1.0" standalone="yes"?> new XDeclaration("1.0", null, "yes")
Note that XDeclaration will happily accept invalid arguments, so it is up to you to get it right.
In many cases the first one, <?xml version="1.0"?>, the form you ask for, is perfect (it is not needed to give encoding if it is just UTF-8 (including ASCII), and it is not needed to specify standalone if its intended value is "no" or if there are no DTDs).
Note that xdoc.ToString() goes do the override from the XNode base class (in my version of .NET) and does not include the XML declaration. You can easily enough create a method to deal with that, like this:
public static string ToStringWithDecl(this XDocument d)
=> $"{d.Declaration}{Environment.NewLine}{d}";
Some of the other answers indicate that the XDeclaration will be respected if you use xdoc.Save or xdoc.WriteTo methods, but that is not quite true:
They might include an XML declaration even if you have none in your XDocument
They might specify the encoding used by the target file, stream, writer, string builder etc. instead of the encoding you gave, or instead of omitting the encoding if you did that in your XDeclaration
They might change your version from e.g. 1.1 into 1.0
Of course, when you save/write to a file, it is a good thing that the declaration matches the true encoding of that file!
But sometimes when you write to a string in mememory, you do not want the utf-16 (even if you realize that .NET strings are in UTF-16 internally). You can use the extension method above instead. Or you can use the following hacked version of the method from EricSch's answer:
string xdocString;
using (var hackedWriter = new SuppressEncodingStringWriter())
{
xdoc.Save(hackedWriter);
xdocString = hackedWriter.ToString();
}
where you have:
// a string writer which claims its encoding is null in order to omit encoding in XML declarations
class SuppressEncodingStringWriter : StringWriter
{
public sealed override Encoding Encoding => null;
}
Addition. Whoever updated the type StringWriter (and its base type TextWriter) to use nuallable reference types, decided that properties such as Encoding and FormatProvider should not be nullable. Maybe that was unfortunate? Anyway, if you have nullable reference types turned on, you may need to write null! instead of just null.

Just type this
var doc =
new XDocument (
new XDeclaration ("1.0", "utf-16", "no"),
new XElement ("blah", "blih")
);
And you get
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<blah>blih</blah>

VB.NET Solution CODE
Code
Dim _root As XElement = <root></root>
Dim _element1 As XElement = <element1>i am element one</element1>
Dim _element2 As XElement = <element2>i am element one</element2>
_root.Add(_element1)
_root.Add(_element2)
Dim _document As New XDocument(New XDeclaration("1.0", "UTF-8", "yes"), _root)
_document.Save("c:\xmlfolder\root.xml")
Output Note(please open output in notepad )
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<element1>i am element one</element1>
<element2>i am element one</element2>
</root>

The easier way is:
var fullXml = $"{xDocument.Declaration}{xDocument}";
If your xDocument.Declaration is empty, just add it.

Related

XDocument adds carriage (\r\n, ecaspe characters) return when generating final xml string

I need to return IHttpActionResult, Ok(xml).
Variable xml is a string data type. The problem is next...
When the program returns string xml, it adds \r\n for a NewLine, string escape characters ().
I want to return a clean xml string.
For example, this string i want to return:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ProxyGlave>
<Glava ID="530064">
<DatumIsporuke>1900-01-01T00:00:00</DatumIsporuke>
</Glava>
<Glava ID="530065">
<DatumIsporuke>1900-01-01T00:00:00</DatumIsporuke>
</Glava>
</ProxyGlave>
But my program returns this:
"
<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n
<ProxyGlave>\r\n
<Glava ID=\"530064\">\r\n
<DatumIsporuke>1900-01-01T00:00:00</DatumIsporuke>\r\n
</Glava>\r\n
<Glava ID=\"530065\">\r\n
<DatumIsporuke>1900-01-01T00:00:00</DatumIsporuke>\r\n
</Glava>\r\n
</ProxyGlave>"
Screenshot from Postman tool:
Code which generates string XML:
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("ProxyGlave",
from gl in glave
select
new XElement("Glava", new XAttribute("ID", gl.DokumentiGlaId),
new XElement("DatumIsporuke", gl.datum_isporuke)))
);
return Ok(xdoc.ToString());
In a Header of the GET request, you need to add Accept key which has value application/xml.
With that information in a header, the app knows what type of value it needs to return.

XML formatting comes out wrong

I am trying to make an XML document through C# with a specific format, but I am having trouble getting it to look right. Here is what it comes out as:
<?xml version="1.0" encoding="UTF-8" ?>
<loanRequest d1p1:ssn=""
d1p2:creditScore=""
d1p3:loanAmount=""
d1p4:loanDuration=""
xmlns:d1p4="26-08-2015 12:41:11"
xmlns:d1p3="147862"
xmlns:d1p2="266"
xmlns:d1p1="765383-2478" />
Here is what it should have been:
<?xml version="1.0" encoding="UTF-8" ?>
<LoanRequest>
<ssn>765383-2478</ssn>
<creditScore>266</creditScore>
<loanAmount>147862</loanAmount>
<loanDuration>2015-08-26 12:41:11.0 CET</loanDuration>
</LoanRequest>
XML manipulation in C# is really confusing to me and I have a hard time piecing together how to do it. The code that I use to make the XML document is as follows:
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode loanRequest = doc.CreateElement("loanRequest");
XmlAttribute ssn = doc.CreateAttribute("ssn", l.SSN);
XmlAttribute creditscore = doc.CreateAttribute("creditScore", ""+l.CreditScore);
XmlAttribute loanamount = doc.CreateAttribute("loanAmount", ""+l.LoanAmount);
XmlAttribute loanduration = doc.CreateAttribute("loanDuration", l.LoanDuration.ToString());
loanRequest.Attributes.Append(ssn);
loanRequest.Attributes.Append(creditscore);
loanRequest.Attributes.Append(loanamount);
loanRequest.Attributes.Append(loanduration);
doc.AppendChild(loanRequest);
Why not use Linq to Xml
XDocument doc = new XDocument(
new XComment("this is a comment"),
new XElement("LoanRequest",
new XElement("ssn", l.SSN),
new XElement("creditScore", l.CreditScore),
new XElement("loanAmount", l.LoanAmount),
new XElement("loanDuration", l.loanDuration.ToString())));
doc.Save(path);
Apparently you add as attributes what should be nodes. Replace the calls of CreateAttribute with calls of AppendChild.

Very simple XML reading in C#.NET

I want to read the following XML file:
Words.xml:
<?xml version="1.0" encoding="utf-8" ?>
<words>
<word>Bat</word>
<word>Dog</word>
<word>Car</word>
</words>
..using XDocument. I keep getting a "Non white space characters cannot be added to content" error with this code:
XDocument doc = new XDocument("words.xml");
foreach (XElement element in doc.Descendants("word"))
{
Console.WriteLine(element.Value);
}
You need to load the document like this:
XDocument doc = XDocument.Load("words.xml");
The reason your original code fails is you are using XDocument (Object[]) constructor that normally expects list of XElement objects like:
var doc = new XDocument(new XElement("Root"));

How to wrtie a XML License Line(ended with a forward slash '/') in C#?

I want to write a XML file as below:
<?xml version="1.0" encoding="UTF-8"?>
<books xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<License licenseId="" licensePath="" />
Some piece of my code attached here
// Create a new file in D:\\ and set the encoding to UTF-8
XmlTextWriter textWriter = new XmlTextWriter("D:\\books.xml", System.Text.Encoding.UTF8);
// Format automatically
textWriter.Formatting = Formatting.Indented;
// Opens the document
textWriter.WriteStartDocument();
// Write the namespace declaration.
textWriter.WriteStartElement("books", null);
// Write the genre attribute.
textWriter.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
textWriter.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
And now I need to write the License Line below in C#
<License licenseId="" licensePath="" />
But I don't know how to move on for I found the Line ended with the forward slash / .Thank you.
I have 2 questions about the way you're doing this:
1) Do you have to use a text writer? If you have access to c# 3.0 then you can use the following:
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XAttribute(XNamespace.Xmlns + "xsd", "http://www.w3.org/2001/XMLSchema"),
new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
new XElement("Equipment",
new XElement("License",
new XAttribute("licenseId", ""),
new XAttribute("licensePath", "")
)
)
);
2) Do you have to declare the two namespaces? It seems to me like you won't use them:
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Equipment",
new XElement("License",
new XAttribute("licenseId", ""),
new XAttribute("licensePath", "")
)
)
);
If you're intending to write multiple License elements to the document, and you have them in an Array, List or some other IEnumerable, you can use something similar to the code below to spit them all out:
IEnumerable<LicenceObjects> licenses = //some code to make them;
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Equipment",
licenses.Select(l =>
new XElement("License",
new XAttribute("licenseId", l.licenseId),
new XAttribute("licensePath", l.licensePath)
)
)
)
);
string xmlDocumentString = doc.ToString();
Of course, if you don't have .NET 3.0, then this is useless to you :(
Calling the WriteEndElement method will automatically take care of adding the forwards slash.
Why don't you just proceed as you started?
textWriter.WriteStartElement("Licence");
textWriter.WriteAttributeString("LicenseId", "");
textWriter.WriteAttributeString("LicensePath", "");
// Other stuff
textWriter.WriteEndDocument();
textWriter.Close();

How to print <?xml version="1.0"?> using XDocument

Is there any way to have an XDocument print the xml version when using the ToString method? Have it output something like this:
<?xml version="1.0"?>
<!DOCTYPE ELMResponse [
]>
<Response>
<Error> ...
I have the following:
var xdoc = new XDocument(new XDocumentType("Response", null, null, "\n"), ...
which will print this which is fine, but it is missing the "<?xml version" as stated above.
<!DOCTYPE ELMResponse [
]>
<Response>
<Error> ...
I know that you can do this by outputting it manually my self. Just wanted to know if it was possible by using XDocument.
By using XDeclaration. This will add the declaration.
But with ToString() you will not get the desired output.
You need to use XDocument.Save() with one of his methods.
Full sample:
var doc = new XDocument(
new XDeclaration("1.0", "utf-16", "yes"),
new XElement("blah", "blih"));
var wr = new StringWriter();
doc.Save(wr);
Console.Write(wr.ToString());
This is by far the best way and most managable:
var xdoc = new XDocument(new XElement("Root", new XElement("Child", "台北 Táiběi.")));
string mystring;
using(var sw = new MemoryStream())
{
using(var strw = new StreamWriter(sw, System.Text.UTF8Encoding.UTF8))
{
xdoc.Save(strw);
mystring = System.Text.UTF8Encoding.UTF8.GetString(sw.ToArray());
}
}
and i say that just because you can change encoding to anything by changing .UTF8 to .Unicode or .UTF32
Late answer to an old question, but I shall try to provide more details than the other answers.
The thing you ask about, is called an XML declaration.
First of all, the XDocument has a property Declaration of type XDeclaration for this. You can either user another overload of the XDocument constructor:
var xdoc = new XDocument(
new XDeclaration("1.0", null, null), // <--- here
new XDocumentType("Response", null, null, "\n"), ...
);
or set the property later:
xdoc.Declaration = new XDeclaration("1.0", null, null);
But depending on how you save or write your XDocument later, the declaration (or parts of it) may be ignored. More on that later.
The XML declaration can have a number of appearances. Here are some valid examples:
<?xml version="1.0"?> new XDeclaration("1.0", null, null)
<?xml version="1.1"?> new XDeclaration("1.1", null, null)
<?xml version="1.0" encoding="us-ascii"?> new XDeclaration("1.0", "us-ascii", null)
<?xml version="1.0" encoding="utf-8"?> new XDeclaration("1.0", "utf-8", null)
<?xml version="1.0" encoding="utf-16"?> new XDeclaration("1.0", "utf-16", null)
<?xml version="1.0" encoding="utf-8" standalone="no"?> new XDeclaration("1.0", "utf-8", "no")
<?xml version="1.0" encoding="utf-8" standalone="yes"?> new XDeclaration("1.0", "utf-8", "yes")
<?xml version="1.0" standalone="yes"?> new XDeclaration("1.0", null, "yes")
Note that XDeclaration will happily accept invalid arguments, so it is up to you to get it right.
In many cases the first one, <?xml version="1.0"?>, the form you ask for, is perfect (it is not needed to give encoding if it is just UTF-8 (including ASCII), and it is not needed to specify standalone if its intended value is "no" or if there are no DTDs).
Note that xdoc.ToString() goes do the override from the XNode base class (in my version of .NET) and does not include the XML declaration. You can easily enough create a method to deal with that, like this:
public static string ToStringWithDecl(this XDocument d)
=> $"{d.Declaration}{Environment.NewLine}{d}";
Some of the other answers indicate that the XDeclaration will be respected if you use xdoc.Save or xdoc.WriteTo methods, but that is not quite true:
They might include an XML declaration even if you have none in your XDocument
They might specify the encoding used by the target file, stream, writer, string builder etc. instead of the encoding you gave, or instead of omitting the encoding if you did that in your XDeclaration
They might change your version from e.g. 1.1 into 1.0
Of course, when you save/write to a file, it is a good thing that the declaration matches the true encoding of that file!
But sometimes when you write to a string in mememory, you do not want the utf-16 (even if you realize that .NET strings are in UTF-16 internally). You can use the extension method above instead. Or you can use the following hacked version of the method from EricSch's answer:
string xdocString;
using (var hackedWriter = new SuppressEncodingStringWriter())
{
xdoc.Save(hackedWriter);
xdocString = hackedWriter.ToString();
}
where you have:
// a string writer which claims its encoding is null in order to omit encoding in XML declarations
class SuppressEncodingStringWriter : StringWriter
{
public sealed override Encoding Encoding => null;
}
Addition. Whoever updated the type StringWriter (and its base type TextWriter) to use nuallable reference types, decided that properties such as Encoding and FormatProvider should not be nullable. Maybe that was unfortunate? Anyway, if you have nullable reference types turned on, you may need to write null! instead of just null.
Just type this
var doc =
new XDocument (
new XDeclaration ("1.0", "utf-16", "no"),
new XElement ("blah", "blih")
);
And you get
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<blah>blih</blah>
VB.NET Solution CODE
Code
Dim _root As XElement = <root></root>
Dim _element1 As XElement = <element1>i am element one</element1>
Dim _element2 As XElement = <element2>i am element one</element2>
_root.Add(_element1)
_root.Add(_element2)
Dim _document As New XDocument(New XDeclaration("1.0", "UTF-8", "yes"), _root)
_document.Save("c:\xmlfolder\root.xml")
Output Note(please open output in notepad )
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<element1>i am element one</element1>
<element2>i am element one</element2>
</root>
The easier way is:
var fullXml = $"{xDocument.Declaration}{xDocument}";
If your xDocument.Declaration is empty, just add it.

Categories