Appending XElement to existing XDocument - c#

I have the following XML string in database.
<?xml version="1.0" encoding="utf-16"?>
<ServiceList>
<Service>
<COMPAT>2</COMPAT>
<EQUIPID>0</EQUIPID>
<TITLE>Collect Call and SMS</TITLE>
<SMSCOMMAND>0</SMSCOMMAND>
<DIALCOMMAND>123</DIALCOMMAND>
<DEACTIVATIONCOMMAND>0</DEACTIVATIONCOMMAND>
<MODE>Dial</MODE>
<DETAIL>Here you go.</DETAIL>
<IMAGE>2014-16-9--16-28-25</IMAGE>
<LONGDESC>
<![CDATA[<p>P<br />P<br />P </p>]]>
</LONGDESC>
<Mechanism>
<Title>Mech Title</Title>
<Description>Here you go.</Description>
<Trigger>Mech Trigger</Trigger>
<Controls>1</Controls>
</Mechanism>
</Service>
</ServiceList>
I need to add/appened the following element inside ServiceList
<Service>
<COMPAT>2</COMPAT>
<EQUIPID>0</EQUIPID>
<TITLE>Collect Call and SMS</TITLE>
<SMSCOMMAND>0</SMSCOMMAND>
<DIALCOMMAND>123</DIALCOMMAND>
<DEACTIVATIONCOMMAND>0</DEACTIVATIONCOMMAND>
<MODE>Dial</MODE>
<DETAIL>Here you go.</DETAIL>
<IMAGE>2014-16-9--16-28-25</IMAGE>
<LONGDESC><![CDATA[<p>P<br />P<br />P </p>]]></LONGDESC>
<Mechanism>
<Title>Mech Title</Title>
<Description>Here you go.</Description>
<Trigger>Mech Trigger</Trigger>
<Controls>1</Controls>
</Mechanism>
</Service>
The c# code is given below where i am creating the document
XElement ServiceList =
new XElement("ServiceList",
new XElement("Service",
new XElement("COMPAT", "2"),
new XElement("EQUIPID", equipId),
new XElement("TITLE", form["Title"]),
new XElement("SMSCOMMAND", smscommand),
new XElement("DIALCOMMAND",dialcommand),
new XElement("DEACTIVATIONCOMMAND", smsdecactivationcommand),
new XElement("MODE", mode),
new XElement("DETAIL", form["Detail"]),
new XElement("IMAGE", Datetime),
new XElement("LONGDESC", new XCData(htmlstring)),
new XElement("Mechanism",
new XElement("Title", form["Mechanism.Title"]),
new XElement("Description", form["Mechanism.Description"]),
new XElement("Trigger", form["Mechanism.Triger"]),
new XElement("Controls", form["Mechanism.Controls"])
)
));
XDocument xml = new XDocument(ServiceList);
I simply convert the above document to string with the help of the following method and insert it to database as string.
public string GetXMLAsString(XDocument myxml)
{
StringWriter sw = new StringWriter();
XmlTextWriter tx = new XmlTextWriter(sw);
myxml.WriteTo(tx);
string str = sw.ToString();
return str;
}

Assuming that you're able to get the XML string back from database and store it in a string variable xml, then you can load it to XDocument as follow :
string xml;
.....
XDocument doc = XDocument.Parse(xml);
And assuming that you can construct the new <Service> node as an XElement object referenced by variable newService, you can easily append it to the doc using XElement.Add() method :
XElement newService;
.....
doc.Root.Add(newService);
Then you need to replace the XML in your database with updated XML :
string updatedXml = doc.ToString();
//save updatedXml to your database
You can easily get XML content by calling ToString() on the XDocument object, as shown in above example.

Related

How Can I add XML declaration?

I Have this Xml output from URL XML
using HTTP GET method
How Can I add this XML declaration?
?xml version="1.0" encoding="ISO-8859-1"?>
This is ServiceContract
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
//BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "{id}")]
XElement GetRecipesByID(string id);
This is implementation,
I convert DataTable To Xml and get from URL
public XElement GetRecipesByID(string id)
{
StringWriter str = new StringWriter();
DataSet dataSet = new DataSet();
dataSet.Tables.Add(Table);
XmlTextWriter xtext = new XmlTextWriter(str);
xtext.Formatting = Formatting.Indented;
xtext.WriteStartDocument();
xtext.WriteStartElement("rss");
xtext.WriteAttributeString("version", "2.0");
xtext.WriteStartElement("channel");
xtext.WriteElementString("title", "GetCard");
xtext.WriteElementString("link", "10.0.0.253");
xtext.WriteElementString("lastBuildDate", " ");
xtext.WriteElementString("generator", "Alikas Feed");
xtext.WriteElementString("error", error);
xtext.WriteElementString("cardid", "RX0016502");
xtext.WriteElementString("name", " ");
xtext.WriteElementString("passport_id", "60001082881");
xtext.WriteElementString("tel", " ");
xtext.WriteEndElement();
xtext.WriteEndDocument();
result = str.ToString();
xtext.Close();
XmlDocument doc = new XmlDocument();
doc.Save(str);
return XElement.Parse(result);
}
When I save this xml in file there is xml declaration but when I try to get this xml from URL xml declaration doesn't show.
I need to show this declaration from URL.
Thank you
WriteStartDocument should already be adding the XML declaration. It uses the Encoding specified by your TextWriter.
You're using a StringWriter which will always report UTF-16 as .NET Strings are in UTF-16. To get ISO-8859-1, you'll need to construct a StreamWriter or some other TextWriter with an explicit encoding.
Have you considered creating an XDocument directly? No need to use XmlWriter in that case.
Try following :
string header = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><rss version=\"2.0\"/>";
XDocument doc = XDocument.Parse(header);
XElement rss = doc.Root;
Boolean error = false;
rss.Add(new XElement("channel", new object[] {
new XElement("title", "GetCard"),
new XElement("link", "10.0.0.253"),
new XElement("lastBuildDate", " "),
new XElement("generator", "Alikas Feed"),
new XElement("error", error),
new XElement("cardid", "RX0016502"),
new XElement("name"),
new XElement("passport_id", "60001082881"),
new XElement("tel")
}));
doc.Save(#"c:\temp\test.xml");
There is an special method for this:
var xmlDoc = new XmlDocument();
xmlDoc.CreateXmlDeclaration("1.0", "ISO-8859-1", null);
xmlDoc.Save(str);
Note from the msdn on encoding parameter: This is the encoding that is used when you save the XmlDocument to a file or a stream; therefore, it must be set to a string supported by the Encoding class, otherwise Save fails.
This seems to work for me
XDocument xel = XDocument.Parse( "<root><el>123</el></root>" );
xel.Declaration = new XDeclaration( "1.0","UTF-8","true" );
xel.Save( #"c:\temp.xml" );

Adding multiple XNamespaces into an XDocument [duplicate]

I have XML like this:
<stream:stream to="lap-020.abcd.co.in" from="sourav#lap-020.abcd.co.in" xml:lang="en" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0"/>
Try to generate the XML using XDocument like this
private readonly XNamespace _streamNamespace = "http://etherx.jabber.org/streams";
private readonly XName _stream;
_stream = _streamNamespace + "stream";
XDocument xdoc=new XDocument(
new XElement(_stream,
new XAttribute("from", "sourav#lap-020.abcd.co.in"),
new XAttribute("to","lap-020.abcd.co.in"),
new XAttribute("xmlns:stream","http://etherx.jabber.org/streams"),
new XAttribute("version","1.0"),
new XAttribute("xml:lang","en")
));
But I get an exception:
Additional information: The ':' character, hexadecimal value 0x3A, cannot be included in a name.
To add namespace declaration you can use XNamespace.Xmlns, and to reference the predefined namespace prefix xml use XNamespace.Xml, for example :
XNamespace stream = "http://etherx.jabber.org/streams";
var result = new XElement(stream + "stream",
new XAttribute("from", "sourav#lap-020.abcd.co.in"),
new XAttribute("to","lap-020.abcd.co.in"),
new XAttribute(XNamespace.Xmlns + "stream", stream),
new XAttribute("version","1.0"),
new XAttribute(XNamespace.Xml+"lang","en"),
String.Empty);
Console.WriteLine(result);
//above prints :
//<stream:stream from="sourav#lap-020.abcd.co.in" to="lap-020.abcd.co.in"
// xmlns:stream="http://etherx.jabber.org/streams" version="1.0"
// xml:lang="en">
//</stream:stream>
you can add the namespace like
XElement root = new XElement("{http://www.adventure-works.com}Root",
new XAttribute(XNamespace.Xmlns + "aw", "http://www.adventure-works.com"),
new XElement("{http://www.adventure-works.com}Child", "child content")
);
This example produces the following output:
<aw:Root xmlns:aw="http://www.adventure-works.com">
<aw:Child>child content</aw:Child>
</aw:Root>

Append Serialized Object Into XML in C#

I have a XML structer like that
<?xml version="1.0" encoding="utf-8"?>
<Product>
<ProductName>da</ProductName>
<PluginPath></PluginPath>
<Instances></Instances>
</Product>
and i serialize my object to string.
<?xml version="1.0"?>
<Instance xmlns:xsi="http://bla bla" xmlns:xsd="bla bla" UniqueId="d4820029b7d7">
<InstanceName>Instance MyTestPluginForm</InstanceName>
<Description>Test Plugin IW</Description>
<AddedDate>2016-10-19T11:05:10.7443404+02:00</AddedDate>
<LogSettings>
<LoggingLevel>None</LoggingLevel>
<LogFilePath /><MaximumSize>100</MaximumSize
<ClearAfterDays>7</ClearAfterDays>
<IsSaveActiviesToEventLog>false</IsSaveActiviesToEventLog>
</LogSettings>
<ProductSpecific/>
</Instance>
So I want to append the second one in the Instances node in the first xml. But as you see both has xml definition on the top and after serializazion i got xmlns:xsi and xmlns:xsd attributes.
How to solve this problem?
PS: I do not want to create XML elements. Because my xml schema is dynamic. It has to be done with serialization. (I already checked this sample)
I solved the problem. using the code here
public static void CreateXmlFile(Instance instance, string filePath)
{
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Product><ProductName>da</ProductName><PluginPath></PluginPath><Instances></Instances></Product>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
xmlDocument.Save(filePath);
XmlNode xnode = xmlDocument.CreateNode(XmlNodeType.Element, "Instances", null);
XmlSerializer xSeriz = new XmlSerializer(typeof(Instance));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings writtersetting = new XmlWriterSettings();
writtersetting.OmitXmlDeclaration = true;
StringWriter stringwriter = new StringWriter();
using (XmlWriter xmlwriter = System.Xml.XmlWriter.Create(stringwriter, writtersetting))
{
xSeriz.Serialize(xmlwriter, instance, ns);
}
xnode.InnerXml = stringwriter.ToString();
XmlNode bindxnode = xnode.SelectSingleNode("Instance");
xmlDocument.DocumentElement.SelectSingleNode("Instances").AppendChild(bindxnode);
xmlDocument.Save(filePath);
}

Writing in xml does not keep the formatting?

I have this string :
<test>I am a test</test>
But when I write it in my xml file, and open it, I have this :
<test>I am a test</test>
I don't know how to use the good formatting. I tried HttpUtility.HtmlDecode, but it does not solve my problem.
Do you have an idea on this ?
Edit : Sorry for not having posted my code before, I thought my problem was really really trivial. Here is a sample I just wrote that resumes the situation (I'm not at work anymore so I don't have the original code) :
XmlDocument xmlDoc = new XmlDocument();
doc.LoadXml("<root>" +
"<test>I am a test</test>" +
"</root>");
string content = xmlDoc.DocumentElement.FirstChild.InnerXml;
XDocument saveFile = new XDocument();
saveFile = new XDocument(new XElement("settings", content));
saveFile.Save("myFile.xml");
I just want my xml file content looks like my original string,
so in my case the file would normally contain :
<settings>
<root>
<test>I am a test</test>
</root>
</settings>
Right ? But instead, I have something like :
<settings><root><test>I am a test</test></root>
</settings>
You can do something along the lines of Converting XDocument to XmlDocument and vice versa to convert the root element of your XmlDocument to an XElement and then add it to your XDocument:
public static class XmlDocumentExtensions
{
public static XElement ToXElement(this XmlDocument xmlDocument)
{
if (xmlDocument == null)
throw new ArgumentNullException("xmlDocument");
if (xmlDocument.DocumentElement == null)
return null;
using (var nodeReader = new XmlNodeReader(xmlDocument.DocumentElement))
{
return XElement.Load(nodeReader);
}
}
}
And then use as follows:
// Get legacy XmlDocument
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root>" +
"<test>I am a test</test>" +
"</root>");
// Add its root element to the XDocument
XDocument saveFile = new XDocument(
new XElement("settings", xmlDoc.ToXElement()));
// Save
Debug.WriteLine(saveFile.ToString());
And the output is:
<settings>
<root>
<test>I am a test</test>
</root>
</settings>
Note this avoids the overhead of converting the XmlDocument to an XML string and re-parsing it from scratch.

SqlXml removes XML header when comes from string

I'm developing a web app with C# and MVC4. Currently I'm working in converting string vars to SqlXml files. I have a XML file with this structure:
<?xml version="1.0" encoding="utf-8"?>
<cfdi:Comprobante xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/TimbreFiscalDigital/TimbreFiscalDigital.xsd" xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" version="3.2" xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</cfdi:Comprobante>
I'm converting the above file to string successfully and then I'm usign the following code that converts a string to a SqlXML.
cfdiDocumento.CFDIXML = Serializar.XMLToSqlXml(comprobante);
Where cfdiDocumento.CFDIXML is a SqlXml var, Serializar.XMLToSqlXml(comprobante) method receives a string and executes the following code:
public static SqlXml XMLToSqlXml(string xmlString)
{
SqlXml sqlXmlFiltro = null;
if (xmlString != null)
{
StringReader sr = new StringReader(xmlString);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Auto;
XmlReader reader0 = XmlReader.Create(sr, settings);
sqlXmlFiltro = new SqlXml(reader0);
}
return sqlXmlFiltro;
}
When the code finishes successfully, the file is correct but is removing the xml header
<?xml version="1.0" encoding="utf-8"?>
The question is: How do I preserve the xml header when convierting to SqlXml var?
If you cannot change the type of your SqlXml attribute, you could try converting the SqlXml to xml document to append xml declaration and get the outer xml:
public string SqlXmlToString(SqlXml sqlXml)
{
XmlDocument doc = new XmlDocument();
doc.Load(sqlXml.CreateReader());
// Create XML declaration with your encoding.
XmlDeclaration xmldecl;
xmldecl = doc.CreateXmlDeclaration("1.0", null, null);
xmldecl.Encoding = "UTF-8";
// Add to the document the created declaration
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmldecl, root);
return doc.OuterXml;
}
Hope this is helpfully

Categories

Resources