Adding multiple XNamespaces into an XDocument [duplicate] - c#

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>

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" );

C# parsing xml with instruction fails

Can anybody tell me why navigating xml with an instruction fails :
StringBuilder sb2 = new System.Text.StringBuilder();
XmlDocument doc = new XmlDocument( );
// --- XML without instruction -> Parsing succeeds
sb1.AppendLine( #"<MetalQuote>");
sb1.AppendLine( #"<Outcome>Success</Outcome>");
sb1.AppendLine( #"<Ask>1073.3</Ask>");
sb1.AppendLine( #"</MetalQuote>");
doc.LoadXml( sb1.ToString( ));
System.Diagnostics.Debug.WriteLine( doc.SelectSingleNode( "//MetalQuote/Outcome").InnerText);
This works well, but the same XML with an instruction fails :
// --- XML with instruction -> Parsing fails
sb2.AppendLine( #"<MetalQuote xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://www.xignite.com/services"" >");
sb2.AppendLine( #"<Outcome>Success</Outcome>");
sb2.AppendLine( #"<Ask>1073.3</Ask>");
sb2.AppendLine( #"</MetalQuote>");
doc.LoadXml( sb2.ToString( ));
System.Diagnostics.Debug.WriteLine( doc.SelectSingleNode( "//MetalQuote/Outcome").InnerText);
I get an exception at the doc.SelectSingleNode statement.
In your version with instructions you are using a custom namespace. Each node will inherit that and you have to take it into account when requesting the node data. One way to do it is to use XmlNamespaceManager. Below a version of your code that applies the manager:
class Program
{
static void Main(string[] args)
{
StringBuilder sb2 = new System.Text.StringBuilder();
XmlDocument doc = new XmlDocument();
// --- XML with instruction -> Parsing fails
sb2.AppendLine(#"<MetalQuote xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://www.xignite.com/services"" >");
sb2.AppendLine(#"<Outcome>Success</Outcome>");
sb2.AppendLine(#"<Ask>1073.3</Ask>");
sb2.AppendLine(#"</MetalQuote>");
doc.LoadXml(sb2.ToString());
// Create a manager
XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
xnm.AddNamespace("abc", #"http://www.xignite.com/services");
// Use the namespace for each node
System.Diagnostics.Debug
.WriteLine(doc.SelectSingleNode(#"//abc:MetalQuote/abc:Outcome", xnm).InnerText);
}
}
There other options available as well. Check this blog post for more details.
Here are two ways with XML Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
StringBuilder sb2 = new System.Text.StringBuilder();
sb2.AppendLine(#"<MetalQuote xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://www.xignite.com/services"" >");
sb2.AppendLine(#"<Outcome>Success</Outcome>");
sb2.AppendLine(#"<Ask>1073.3</Ask>");
sb2.AppendLine(#"</MetalQuote>");
XDocument doc = XDocument.Parse(sb2.ToString());
XElement outCome = doc.Descendants().Where(x => x.Name.LocalName == "Outcome").FirstOrDefault();
XElement metalQuote = (XElement)doc.FirstNode;
XNamespace ns = metalQuote.Name.Namespace;
XElement outCome2 = doc.Descendants(ns + "Outcome").FirstOrDefault();
}
}
}
​

Windows phone 8.1 XDocument xml serialization C#

I'm creating a Windows Phone 8.1 app, and I need to serialize my data to XML.
I have two functions; the first one is creating a document where I can later put my retrieved data.
public async Task make()
{
using (var questions = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
"data.xml",
CreationCollisionOption.OpenIfExists))
{
XDocument xml = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Root")
);
xml.Save(questions);
}
}
The second one is making serialization to my xml file:
public async Task serial(Tsk tak)
{
using (var questions = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
"data.xml",
CreationCollisionOption.OpenIfExists))
{
XDocument xml = XDocument.Load(questions);
xml.Root.Add(new XAttribute("Date", tak.Date),
new XElement("time", tak.Time),
new XElement("text", tak.Text)
);
xml.Save(questions);
}
}
The first xml function is making this code:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root />
When I'm running the second function I've got this error: root element is missing. Can anyone tell me how I can get this serialization to work?
Try this, you might need to doctor it a bit:
1) create the document
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("root");
doc.AppendChild(root);
file = await ApplicationData.Current.LocalFolder.CreateFileAsync("data.xml");
await FileIO.WriteTextAsync(file, doc.GetXml());
Debug.WriteLine("Done creating file.");
2) write the new data to the document
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("data.xml");
XDocument doc = XDocument.Load(file.Path);
XElement newQuestion = new XElement("Question",
new XElement("time", tak.Time),
new XElement("text", tak.Text)
).SetAttributeValue("Date", tak.Date);
doc.Root.Add(newQuestion);
await FileIO.WriteTextAsync(file, doc.Root.ToString());

Appending XElement to existing XDocument

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.

Append XML Node to Existing XML File

I have an XML in the following format
<Attachment>
<AttachmentName>Top Nav Menu.docx</AttachmentName>
<Subject>Attachment1</Subject>
<Sender>JameelM#orioninc.com</Sender>
</Attachment>
I want to attach another Attachment like above after the attachment close node. Below are the code that i have written for writing xml file
var doc = new XDocument(
new XDeclaration("1.0", "utf-16", "true"),
new XProcessingInstruction("test", "value"),
new XElement("Attachment",new XElement("AttachmentName", attachment.Name),
new XElement("Subject", exchangeEmailInformation.Subject),
new XElement("Sender", exchangeEmailInformation.Sender
)));
doc.Save(ConfigInformation.BackUpPath + FolderId[index]+"\\Attachments"+index+".xml");
Create root node for your attachments:
var doc = new XDocument(
new XDeclaration("1.0", "utf-16", "true"),
new XProcessingInstruction("test", "value"),
new XElement("Attachments",
new XElement("Attachment",
new XElement("AttachmentName", attachment.Name),
new XElement("Subject", exchangeEmailInformation.Subject),
new XElement("Sender", exchangeEmailInformation.Sender)
)));
When you decide to append another attachment, load document and add attachment to root:
doc.Root.Add(new XElement("Attachment",
new XElement("AttachmentName", attachment.Name),
new XElement("Subject", exchangeEmailInformation.Subject),
new XElement("Sender", exchangeEmailInformation.Sender)
));
I would use the XMLSerializer class. There you can handle your XML files just as if they are classes. Just have a look, you will like it :)
Load XML -> Use Classes in Code (modify, delete, add) -> Serialize back into XML

Categories

Resources