Add XDeclaration to XDocument after it's constructed - c#

I have an XmlSerializer which I use to Serialize an object to an XDocument.
var doc = new XDocument();
using (var writer = doc.CreateWriter())
{
xmlSerializer.Serialize(writer, object);
}
After this is done, I want to add a XDeclaration:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
I construct this XDeclaration as described below:
var decl = new XDeclaration("1.0", "UTF-8", "no");
However, when I try to add this XDeclartion to my XDocument, I get the following error:
System.ArgumentException : Non white space characters cannot be added to content.
I searched Google for some time but all I've found is adding the XDeclaration to the constructor of the XDocument which in my case (when filling it with a XmlWriter) is not acceptable.

Use property XDocument.Declaration
EDIT:
Sample code:
var xmlSerializer = new XmlSerializer(typeof(int));
var doc = new XDocument();
var decl = new XDeclaration("1.0", "utf-8", "no");
doc.Declaration = decl;
using (var writer = doc.CreateWriter())
{
xmlSerializer.Serialize(writer, 1);
}
doc.Save(File.Create("x.xml"));
This code produced following output:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<int>1</int>

Related

XML Namespace prefix only on root

I am creating an XML document using the Task Factory XML Output Destination task though the output needs some tweaking and I can't seem to find a way to do this within the task so figured I would be able to do this via the script component with C#.
This is the XML I am working with
<?xml version="1.0" encoding="utf-8"?>
<CSDS xmlns="http://www.datadictionary.nhs.uk/messages/CSDS-v1-0">
<CYP000>
<C000010>1.0</C000010>
</CYP000>
</CSDS>
And I need to change the XML to look like:
<?xml version="1.0" encoding="utf-8"?>
<CSDS:CSDS xmlns:CSDS="http://www.datadictionary.nhs.uk/messages/CSDS-v1-0">
<CYP000>
<C000010>1.0</C000010>
</CYP000>
</CSDS>
I have tried creating a new XDocument declaring the namespace and adding the source elements in but this adds the namespace to all elements.
string xmlFile = #"C:\Temp\csds.xml";
string newXmlFile = #"C:\Temp\csds-new.xml";
XDocument sourceXml = XDocument.Load(xmlFile);
XNamespace ns = "http://www.datadictionary.nhs.uk/messages/CSDS-v1-0";
XDocument newXml = new XDocument(new XDeclaration("1.0", "utf-8", null));
XElement newRoot = new XElement(ns + "CSDS",
new XAttribute(XNamespace.Xmlns + "CSDS", ns.NamespaceName));
newRoot.Add(sourceXml.Root.Elements());
newRoot.Save(newXmlFile);
Output
<?xml version="1.0" encoding="utf-8"?>
<CSDS:CSDS xmlns:CSDS="http://www.datadictionary.nhs.uk/messages/CSDS-v1-0">
<CSDS:CYP000>
<CSDS:C000010>1.0</CSDS:C000010>
</CSDS:CYP000>
</CSDS:CSDS>
I have found that doing the following after loading my file works along with the rest of my code:
foreach (var descendants in sourceXml.Root.Descendants())
descendants.Name = descendants.Name.LocalName;

How to convert Object to XML Without Namespace?

I have this code, how I can remove the namespace from output xml
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(OrderTable));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, null);
xs.Serialize(xmlTextWriter, ot);
string result = Encoding.Default.GetString(memoryStream.ToArray());
<?xml version="1.0" ?>
- <OrderTable xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ForceUpdate>false</ForceUpdate>
<TableId xsi:nil="true" />
<UpdatedBy>Jack</UpdatedBy>
</OrderTable>
I want to remove xmlns, I googled, but those are not helping me.
I want to remove xmlns
All you have to do is using XmlSerializerNamespaces
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
xs.Serialize(xmlTextWriter, ot, ns);

Why does XDeclaration ignore the encoding parameter I set

The problem
I am trying to generate a XML file with the XDeclaration that should result in the following
<?xml version="1.0"?>.
What I keep getting when I run my piece of code is this
<?xml version="1.0" encoding="utf-8"?>.
So the problem is, no matter what I change in the encoding parameter of my XDeclaration it keeps adding an encoding tag to my declaration.
My question
Is what I want even possible? And if so could someone explain it to me?
What I have tried
First I tried to set OmitXmlDeclaration to true. But that removes my declaration entirely and then I can't use the XDecleration class at all..
Secondly, when I set my XDecleration to this:
new XDeclaration("1.0", string.Empty, "yes")
I get this
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
and when I set my XDecleration to this:
new XDeclaration("1.0", string.Empty, string.Empty)
I get this
<?xml version="1.0" encoding="utf-8"?>
So I know that it does respond to what I enter, but the encoding part does not.
EDIT: I also tried to set the parameters to null instead of string.Empty. This doesn't work either.
My Code
public FileResult Download()
{
var doc = new XDocument(
new XDeclaration("1.0", string.Empty, string.Empty),
new XElement("foo",
new XAttribute("hello", "world")
)
);
using (var stream = new MemoryStream())
{
var settings = new XmlWriterSettings()
{
OmitXmlDeclaration = false,
Indent = true,
};
using (var writer = XmlWriter.Create(stream, settings))
{
doc.Save(writer);
}
stream.Position = 0;
return File(stream.ToArray(), "text/xml", "HelloWorld.xml");
}
}
EDIT
De solution was given to me by #HimBromBeere. He gave an answer with the following link included.
cookcomputing.com/blog/archives/000577.html. Here you overide your encoding parameter. This worked for me.
By default XML save method will override the encoding method supplied by us via XDeclaration while saving the Xdocument. The easiest way is to create a memorystream and patch the encoding method. Refer The following code fragment
public static void PatchEncoding(string xmlPath, XDocument xmlDoc, string encoding = "windows-1251")
{
using (var stream = new MemoryStream())
using (XmlTextWriter xmlwriter = new XmlTextWriter(stream, Encoding.GetEncoding(encoding)))
{
xmlDoc.Save(xmlPath);
}
}

Confusion about How to populate xmlfile

I need to create a xml file programmatically like below.
<Players>
<Player>
<Name>C.Ronaldo</Name>
<Team>Man Utd</Team>
<Position>Midfielder</Position>
</Player>
</Players>
The problem is that the xml file which is created is not what I expect .How can fix this code
Thanks in advance
XDocument xdoc = new XDocument(new XDeclaration("1.0", "utf-16", null));
XElement root = new XElement("Players");
xdoc.Add(root);
XElement player = new XElement("Player");
XElement[] el = {
new XElement("Name","xxx"),
new XElement("Team","dfdf"),
new XElement("Position","dsds")
};
xdoc.Root.Add(el);
xdoc.Save("myxml.xml", SaveOptions.None);
MessageBox.Show("ok");
The simpliest solution for your code would be to replace
xdoc.Root.Add(el);
with this:
player.Add(el);
xdoc.Root.Add(player);

Add <?xml version="1.0" ?> to the top of a xml file after xsl transform

I have successfully been able to transform a simple xml file with data to another xml file (excel template) using a xsl template, this is what my xsl file looks like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" standalone="yes"/>
<xsl:template match="/">
<xsl:processing-instruction name="mso-application">
<xsl:text>progid="Excel.Sheet"</xsl:text>
</xsl:processing-instruction>
...(stuff here)...
</xsl:template>
</xsl:stylesheet>
The resulting xml file is written out correctly BUT with the exception of including
<?xml version="1.0"?>
at the top of the file. How can I get it to appear at the top?
Currently my resulting xml file starts with:
<?mso-application progid="Excel.Sheet"?>
...(rest of file)...
But what I need it to do is:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
.(rest of file)...
I'm doing this transform through a windows form with the following code:
XPathDocument myXPathDoc = new XPathDocument(xmlfile);
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load(xslfile);
XmlTextWriter myWriter = new XmlTextWriter(xmlexcelfile, null);
myWriter.Formatting = Formatting.Indented;
myWriter.Namespaces = true;
myXslTrans.Transform(myXPathDoc, null, myWriter);
myWriter.Close();
I've tried playing around with the xsl:output standalone="yes/no", as well as omit-xml-declaration="no". I've also tried (in the C#) code adding myWriter.WriteStartDocument(); before transforming but that was not allowed. I have tried searching online for this as well and keep coming back to the standalone="yes" but that isn't working. Is there something I am missing here? Oh and in case you are wondering why I need to have the
<?xml version="1.0"?>
at the top of the resulting file, it's because when opening the xml file with excel, excel doesn't recognize it correctly but if it is included then excel opens it correctly...
You can do this
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />
or something similar to this using XmlWriterSettings
Edit: Added more code. Previous was missing some parts
XmlWriterSettings writerSettings = null;
XsltArgumentList transformationArguments = null;
XslCompiledTransform transformer = null;
MemoryStream memoryStream = null;
XPathDocument xPathDocument = null;
StringBuilder sb = null;
XmlWriter writer = null;
XmlDocument resultXml = null;
try
{
writerSettings = new XmlWriterSettings();
writerSettings.OmitXmlDeclaration = false; // This does it
writerSettings.Indent = true;
transformationArguments = new XsltArgumentList();
transformer = new XslCompiledTransform();
memoryStream = new MemoryStream(System.Text.Encoding.Default.GetBytes(xml.OuterXml));
xPathDocument = new XPathDocument(new StreamReader(memoryStream));
sb = new StringBuilder();
// give the settings to the writer here
writer = XmlWriter.Create(sb, writerSettings);
// this is not mandatory, obviously, just passing parameters to my xslt file
foreach (KeyValuePair<string, object> parameter in parameters)
{
transformationArguments.AddParam(parameter.Key, string.Empty, parameter.Value);
}
using (Stream strm = Assembly.GetExecutingAssembly().GetManifestResourceStream("Lib.XSLTFile1.xslt"))
using (XmlReader reader = XmlReader.Create(strm))
{
transformer.Load(reader);
transformer.Transform(xPathDocument, transformationArguments, writer);
}
resultXml = new XmlDocument();
resultXml.LoadXml(sb.ToString());
// for testing only
File.AppendAllText(#"Your path goes here\result.xml", resultXml.OuterXml);
}
catch (Exception)
{
throw;
}
This is how I do it, but this code is specifically written to create an instance of a XmlDocument. I'm sure you can adapt to your needs.

Categories