I have two class : Osoba, test
public class test
{
public string raz { get; set; }
public string dwa { get; set; }
}
public class Osoba
{
public test tehe { get; set; }
}
I also add namespaces to main root and seralize
Osoba ne = new Osoba();
test t1 = new praca2.test();
t1.dwa = "fgfg";
t1.raz = "dfdfdfdf";
ne.tehe = t1;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
ns.Add("d", "http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields");
ns.Add("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
XmlSerializer xsSubmit = new XmlSerializer(typeof(Osoba));
var xml = #"D:\dupa1.xml";
using (var stream = new FileStream(xml, FileMode.Create))
{
using (XmlWriter writer = XmlWriter.Create(stream))
{
xsSubmit.Serialize(writer, ne,ns);
xml = stream.ToString(); // Your XML
}
}
I get
<?xml version="1.0" encoding="utf-8"?>
<Osoba xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"xmlns:d="http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">
<tehe>
<raz>dfdfdfdf</raz>
<dwa>fgfg</dwa>
</tehe>
</Osoba>
I want add to node namespaces examle:
...
<pc:tehe>
<dfs:raz>dfdfdfdf</dfs:raz>
<dfs:dwa>fgfg</dfs:dwa>
</pc:tehe>
How I can do it?
I try add class atribute which set namespace
[XmlRoot("Node", Namespace="http://flibble")]
but it bad idea
You're almost there you just need to modify your classes slightly:
public class test
{
[XmlElement(Namespace = "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution")]
public string raz { get; set; }
[XmlElement(Namespace = "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution")]
public string dwa { get; set; }
}
public class Osoba
{
[XmlElement(Namespace = "http://schemas.microsoft.com/office/infopath/2007/PartnerControls")]
public test tehe { get; set; }
}
Sample implementation copied mostly from yours:
class Program
{
static void Main(string[] args)
{
Osoba ne = new Osoba();
test t1 = new test();
t1.dwa = "fgfg";
t1.raz = "dfdfdfdf";
ne.tehe = t1;
XmlSerializer xsSubmit = new XmlSerializer(typeof(Osoba));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
ns.Add("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
var xml = #"D:\dupa1.xml";
using (var stream = new FileStream(xml, FileMode.Create))
{
using (XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8))
{
xsSubmit.Serialize(writer, ne, ns);
}
}
}
}
You will get this XML:
<?xml version="1.0" encoding="utf-8"?>
<Osoba xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
<pc:tehe>
<dfs:raz>dfdfdfdf</dfs:raz>
<dfs:dwa>fgfg</dfs:dwa>
</pc:tehe>
</Osoba>
Hth...
Uisng xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication42
{
class Program
{
static void Main(string[] args)
{
string xmlHeader =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<Osoba xmlns:dfs=\"http://schemas.microsoft.com/office/infopath/2003/dataFormSolution\"" +
" xmlns:pc=\"http://schemas.microsoft.com/office/infopath/2007/PartnerControls\"" +
" xmlns:d=\"http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields\">" +
"</Osoba>";
XDocument doc = XDocument.Parse(xmlHeader);
XElement osoba = doc.Root;
XNamespace dfsNs = osoba.GetNamespaceOfPrefix("dfs");
XNamespace pcNs = osoba.GetNamespaceOfPrefix("pc");
osoba.Add(new XElement(pcNs + "tehe", new object[] {
new XElement(dfsNs + "raz", "dfdfdfdf"),
new XElement(dfsNs + "dwa", "fgfg")
}));
}
}
}
I think you are new at C#.I suggest you to study C# basics, design patterns and repository pattern.For your requirement you can use below codes
public class Tehe
{
public string Raz { get; set; }
public string Dwa { get; set; }
}
public class TeheRepository
{
private System.Xml.Linq.XDocument xmlDatas;
public TeheRepository(string filePath)
{
xmlDatas = XDocument.Load(filePath);
}
public IEnumerable<Tehe> FindAll()
{
return xmlDatas.Elements().Elements().Select(tehe =>
{
Tehe t = new Tehe();
t.Dwa = tehe.Elements().ElementAt(1).Value;
t.Raz = tehe.Elements().ElementAt(0).Value;
return t;
});
}
}
Related
I am getting error with deserialization. It says error in xml document.
public T XmlDeserialiseResponseObject<T>(string xml)
{
T returnedXmlClass;
try
{
xml = XmlResponseObjectCleaner(xml);
var doc = new XmlDocument();
doc.LoadXml(xml);
var reader = new XmlNodeReader(doc.DocumentElement);
var ser = new XmlSerializer(typeof(T));
returnedXmlClass = (T)ser.Deserialize(reader);
}
catch (Exception ex)
{
throw ex;
}
return returnedXmlClass;
}
My XML :
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/elope/'><soap:Body><GetBenefitStatusFault xmlns:ns2='http://schemas.somesite.co.za/somesite/some/' schemaVersion='1.0'>
<ErrorCode>3513</ErrorCode>
<ErrorMessage>Membership details not valid: Match on initial not found</ErrorMessage>
</GetBenefitStatusFault></soap:Body></soap:Envelope>
XmlResponseObjectCleaner:
private string XmlResponseObjectCleaner(string xml)
{
var sb = new StringBuilder();
sb.Append(xml);
sb.Replace(#"""", "'");
sb.Replace("<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>", "");
sb.Replace("</env:Envelope>", "");
sb.Replace("<env:Header/>", "");
sb.Replace("<env:Body>", "");
sb.Replace("ns3:", "");
sb.Replace("ns2:", "");
sb.Replace("</env:Body>", "");
sb.Replace("env", "");
sb.Replace("T00:00:00.000+02:00", "");
sb.Replace("T00:00:00.000Z", "");
return sb.ToString();
}
You could:
load the XML into a DOM and pick out the Body element and parse the OuterXml from there
start at the envelope
Here's an approach for 2:
using System.IO;
using System.Xml.Serialization;
static class P
{
static void Main()
{
const string xml = #"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/elope/'><soap:Body><GetBenefitStatusFault xmlns:ns2='http://schemas.somesite.co.za/somesite/some/' schemaVersion='1.0'>
<ErrorCode>3513</ErrorCode>
<ErrorMessage>Membership details not valid: Match on initial not found</ErrorMessage>
</GetBenefitStatusFault></soap:Body></soap:Envelope>";
var obj = XmlDeserialiseResponseObject<GetBenefitBody>(xml);
if (obj.GetBenefitStatusFault is Fault f)
{
System.Console.WriteLine(f.ErrorCode);
System.Console.WriteLine(f.ErrorMessage);
}
}
public static T XmlDeserialiseResponseObject<T>(string xml)
{
var ser = new XmlSerializer(typeof(Envelope<T>));
var obj = (Envelope<T>)ser.Deserialize(new StringReader(xml));
return obj.Body;
}
}
[XmlRoot("Envelope", Namespace = "http://schemas.xmlsoap.org/soap/elope/")]
public class Envelope<T>
{
public T Body { get; set; }
}
public class GetBenefitBody
{
[XmlElement(Namespace = "")]
public Fault GetBenefitStatusFault { get; set; }
}
public class Fault
{
public int ErrorCode { get; set; }
public string ErrorMessage { get; set; }
}
I am having a problem with deserialization of an array which comes from the SOAP response. It returns null, but in response I can actually see a correct xml message. Maybe someone can see what's wrong in my code. Thanks in advance.
SOAP response:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns-wp="imcwp" xmlns:ns-hostax="imchostax" xmlns:ns-ilms="imcilms" xmlns:ns-qtms="imcqtms" xmlns:ns-tptms="imctptms">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns-wp:strTrailerRequest-TrailerResponse>
<ns-wp:Trailer>
<ns-wp:TrailerId>T001</ns-wp:TrailerId>
<ns-wp:TrailerType>Flat Extender</ns-wp:TrailerType>
</ns-wp:Trailer>
<ns-wp:Trailer>
<ns-wp:TrailerId>T002</ns-wp:TrailerId>
<ns-wp:TrailerType>Flat Extender</ns-wp:TrailerType>
</ns-wp:Trailer>
<ns-wp:Trailer>
<ns-wp:TrailerId>T003</ns-wp:TrailerId>
<ns-wp:TrailerType>Flat Extender</ns-wp:TrailerType>
</ns-wp:Trailer>
</ns-wp:strTrailerRequest-TrailerResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Response Model:
[XmlRoot(ElementName = "strTrailerRequest-TrailerResponse", Namespace = "imcwp")]
public class strTrailerRequestTrailerResponse
{
[XmlArray("strTrailerRequest-TrailerResponse", Namespace = "imcwp")]
[XmlArrayItem("Trailer", Namespace = "imcwp")]
public List<Trailer> Trailers { get; set; }
}
Parse Method:
private strTrailerRequestTrailerResponse ParseTrailerResponse(string response)
{
var soap = XDocument.Parse(response);
XNamespace ns = "imcwp";
var trailerResponseNode = soap.Descendants(ns + "strTrailerRequest-TrailerResponse").FirstOrDefault().ToString();
var result = Deserialize<strTrailerRequestTrailerResponse>(trailerResponseNode);
return result;
}
Why not just deserilize the whole object, in that case u dont need xDocument and querying:
var envelop = Deserialize<Envelope>(response);
foreach (var strTrailerRequestTrailerResponseTrailer in envelop.Body.strTrailerRequestTrailerResponse)
{
}
and yr Deserialize method:
public static T Deserialize<T>(string response)
{
var serializer = new XmlSerializer(typeof(T));
using(TextReader reader = new StringReader(response))
{
return (T)serializer.Deserialize(reader);
}
}
If you still want to go with yr way using XDocument, it's ok yr Deserialize method should the same as I defined. if you wont try:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "imcwp")]
public partial class strTrailerRequestTrailerResponseTrailer
{
public string TrailerId { get; set; }
public string TrailerType { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "imcwp")]
[System.Xml.Serialization.XmlRootAttribute("strTrailerRequest-TrailerResponse", Namespace = "imcwp", IsNullable = false)]
public partial class strTrailerRequestTrailerResponse
{
[System.Xml.Serialization.XmlElementAttribute("Trailer")]
public strTrailerRequestTrailerResponseTrailer[] Trailer { get; set; }
}
For simple xml you can use xml linq. See code below :
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace Certificate
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
XElement soap = doc.Root;
XNamespace ns = soap.GetNamespaceOfPrefix("ns-wp");
List<Trailer> trailers = doc.Descendants(ns + "Trailer").Select(x => new Trailer()
{
trailerId = (string)x.Element(ns + "TrailerId"),
trailerType = (string)x.Element(ns + "TrailerType")
}).ToList();
}
}
public class Trailer
{
public string trailerId { get; set; }
public string trailerType { get;set;}
}
}
http://rtt.metroinfo.org.nz/RTT/Public/Utility/File.aspx?ContentType=SQLXML&Name=JPPlatform.xml
http://rtt.metroinfo.org.nz/RTT/Public/Utility/File.aspx?Name=JPRoutePositionET.xml&ContentType=SQLXML&PlatformTag=536
Both of those are my sample data which I am pulling down using HttpClient, I want to grab the attributes(?) such as PlatformTag, ETA and the like.
This is using Univeral Apps for Windows 10 mobile and Desktop. But I can't figure out what's going on to do it.
XDocument Document = XDocument.Parse(RESPONSE_CONSTANT);
var Stops = from Stop in Document.Descendants("Platform")
select new
{
Platformtag = (string)Stop.Attribute("PlatformTag"),
Platformno = (string)Stop.Attribute("PlatformNo")};
foreach (var item in Stops)
BusData.Text = item.Platformtag;
}
Is what I currently have, but nothing comes from it, it just sits there like it sees nothing, from here I don't know enough about XML Parsing to find a next step.
Note: Response_Constant contains data like this: http://rtt.metroinfo.org.nz/RTT/Public/Utility/File.aspx?Name=JPRoutePositionET.xml&ContentType=SQLXML&PlatformTag=536
Try following. Had to modify xml to replace ampersand.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication14
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
xml = xml.Replace("&", "&");
StringReader sReader = new StringReader(xml);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader reader = XmlReader.Create(sReader);
List<Platform> platforms = new List<Platform>();
while (!reader.EOF)
{
if (reader.Name != "Platform")
{
reader.ReadToFollowing("Platform");
}
if (!reader.EOF)
{
XElement platform = (XElement)XElement.ReadFrom(reader);
platforms.Add(new Platform()
{
tag = (int)platform.Attribute("PlatformTag"),
no = (int?)platform.Attribute("PlatformNo"),
name = (string)platform.Attribute("Name"),
bearingToRoad = (double?)platform.Attribute("BearingToRoad"),
roadName = (string)platform.Attribute("RoadName"),
lat = (double)platform.Element(platform.Name.Namespace + "Position").Attribute("Lat"),
_long = (double)platform.Element(platform.Name.Namespace + "Position").Attribute("Long")
});
}
}
}
}
public class Platform
{
public int tag { get; set; }
public int? no { get; set; }
public string name { get; set; }
public double? bearingToRoad { get; set; }
public string roadName { get; set; }
public double lat { get; set; }
public double _long { get; set; }
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) //Save On Form Closing
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(path + "\\Address Book - Me \\settings.xml");
XmlNode xNode = xDoc.SelectSingleNode("People");
xNode.RemoveAll();
foreach (Person pe in people)
{
XmlNode xTop = xDoc.CreateElement("People");
XmlNode xName = xDoc.CreateElement("Name");
XmlNode xLastName = xDoc.CreateElement("LastName");
XmlNode xStreet = xDoc.CreateElement("Address");
XmlNode xPhone = xDoc.CreateElement("Phone");
XmlNode xEmail = xDoc.CreateElement("Email");
XmlNode xDate = xDoc.CreateElement("Birth");
XmlNode xCity = xDoc.CreateElement("City");
XmlNode xState = xDoc.CreateElement("State");
XmlNode xCountry = xDoc.CreateElement("Country");
XmlNode xDetails = xDoc.CreateElement("Detail");
xName.InnerText = pe.Name;
xLastName.InnerText = pe.LastName;
xStreet.InnerText = pe.StreetAdress;
xPhone.InnerText = pe.Phone;
xEmail.InnerText = pe.Email;
xDate.InnerText = pe.Date.ToFileTime().ToString();
xCity.InnerText = pe.City;
xState.InnerText = pe.State;
xCountry.InnerText = pe.Country;
xDetails.InnerText = pe.Details;
xTop.AppendChild(xName);//adding a new node
xTop.AppendChild(xLastName);
xTop.AppendChild(xStreet);
xTop.AppendChild(xPhone);
xTop.AppendChild(xEmail);
xTop.AppendChild(xDate);
xTop.AppendChild(xCity);
xTop.AppendChild(xState);
xTop.AppendChild(xCountry);
xTop.AppendChild(xDetails);
xDoc.DocumentElement.AppendChild(xTop);
}
xDoc.Save(path + "\\Address Book - Me \\settings.xml");//
I'm trying to make an agenta that saves information and reload them after I restart my app. But when I closed my program nothing works and that's it:
Xml An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll and Additional information: Root element is missing.
Please help me.
From comment: the exception was thrown here: xDoc.Load(path + "\\Address Book - Me \\settings.xml");
Delete your folder with .xml file. Then made a new .xml file with this.
XmlTextWriter xW = new XmlTextWriter(YourPath, YourEncoding);
xW.WriteStartElement(Your Tag);
xW.WriteEndElement();
xW.Close();
The simplest way would be to use XmlSerialization as in the example below.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
var settings = new Settings();
settings.People.Add(new Person { Name = "Name", LastName = "LastName", City="City", Country="Country", Date="11/11/11", Details="Details", Email="Email", Phone="Phone", State="State", Street="Steet" });
settings.Save("c:\\test.xml");
settings = Settings.TryLoad("c:\\test.xml");
}
[Serializable]
public class Settings
{
public Settings()
{
}
public List<Person> People
{
get { return people; }
set { people = value; }
}
List<Person> people = new List<Person>();
public void Save(string path)
{
XmlSerializer xs = new XmlSerializer(typeof(Settings));
using (var sw = new StreamWriter(File.Open(path, FileMode.OpenOrCreate)))
{
xs.Serialize(sw, this);
}
}
public static Settings TryLoad(string path)
{
Settings settings = null;
XmlSerializer xs = new XmlSerializer(typeof(Settings));
using (var sw = new StreamReader(File.OpenRead(path)))
{
try
{
settings = xs.Deserialize(sw) as Settings;
}
catch (Exception)
{
// skip
}
}
return settings;
}
}
[Serializable]
public class Person
{
public Person()
{
}
public string Name { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Date { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
public string Details { get; set; }
}
}
}
I am using a DataContractSerializer to serialize an object to XML. The main object is SecurityHolding with the namespace "http://personaltrading.test.com/" and contains a property called Amount that's a class with the namespace "http://core.test.com". When I serialize this to XML I get the following:
<ArrayOfSecurityHolding xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://personaltrading.test.com/">
<SecurityHolding>
<Amount xmlns:d3p1="http://core.test.com/">
<d3p1:Amount>1.05</d3p1:Amount>
<d3p1:CurrencyCode>USD</d3p1:CurrencyCode>
</Amount>
<BrokerageID>0</BrokerageID>
<BrokerageName i:nil="true" />
<RecordID>3681</RecordID>
</SecurityHolding></ArrayOfSecurityHolding>
Is there anyway I can control the d3p1 prefix? Am I doing something wrong or should I be doing something else?
Firstly, the choice of namespace alias should make no difference to a well-formed parser.
But; does it have to be DataContractSerializer? With XmlSerializer, you can use the overload of Serialize that accepts a XmlSerializerNamespaces. This allows you to pick and choose the namespaces and aliases that you use.
Ultimately; DataContractSerializer is not intended to give full xml control; that isn't its aim. If you want strict xml control, XmlSerializer is a better choice, even if it is older (and has some nuances/foibles of its own).
Full example:
using System;
using System.Xml.Serialization;
public class Amount
{
public const string CoreNamespace = "http://core.test.com/";
[XmlElement("Amount", Namespace=CoreNamespace)]
public decimal Value { get; set; }
[XmlElement("CurrencyCode", Namespace = CoreNamespace)]
public string Currency { get; set; }
}
[XmlType("SecurityHolding", Namespace = SecurityHolding.TradingNamespace)]
public class SecurityHolding
{
public const string TradingNamespace = "http://personaltrading.test.com/";
[XmlElement("Amount", Namespace = Amount.CoreNamespace)]
public Amount Amount { get; set; }
public int BrokerageId { get; set; }
public string BrokerageName { get; set; }
public int RecordId { get; set; }
}
static class Program
{
static void Main()
{
var data = new[] {
new SecurityHolding {
Amount = new Amount {
Value = 1.05M,
Currency = "USD"
},
BrokerageId = 0,
BrokerageName = null,
RecordId = 3681
}
};
var ser = new XmlSerializer(data.GetType(),
new XmlRootAttribute("ArrayOfSecurityHolding") { Namespace = SecurityHolding.TradingNamespace});
var ns = new XmlSerializerNamespaces();
ns.Add("foo", Amount.CoreNamespace);
ser.Serialize(Console.Out, data, ns);
}
}
Output:
<ArrayOfSecurityHolding xmlns:foo="http://core.test.com/" xmlns="http://personaltrading.test.com/">
<SecurityHolding>
<foo:Amount>
<foo:Amount>1.05</foo:Amount>
<foo:CurrencyCode>USD</foo:CurrencyCode>
</foo:Amount>
<BrokerageId>0</BrokerageId>
<RecordId>3681</RecordId>
</SecurityHolding>
</ArrayOfSecurityHolding>
I have solved this problem slightly differently to Marc that can be implemented in a base class.
Create a new attribute to define the additional XML namespaces that you will use in your data contract.
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public sealed class NamespaceAttribute : Attribute
{
public NamespaceAttribute()
{
}
public NamespaceAttribute(string prefix, string uri)
{
Prefix = prefix;
Uri = uri;
}
public string Prefix { get; set; }
public string Uri { get; set; }
}
Add the attribute to your data contracts.
[DataContract(Name = "SomeObject", Namespace = "http://schemas.domain.com/namespace/")]
[Namespace(Prefix = "a", Uri = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
[Namespace(Prefix = "wm", Uri = "http://schemas.datacontract.org/2004/07/System.Windows.Media")]
public class SomeObject : SerializableObject
{
private IList<Color> colors;
[DataMember]
[DisplayName("Colors")]
public IList<Colors> Colors
{
get { return colors; }
set { colours = value; }
}
}
Then in your Save method, use reflection to get the attributes and then write them to the file.
public static void Save(SerializableObject o, string filename)
{
using (Stream outputStream = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
if (outputStream == null)
throw new ArgumentNullException("Must have valid output stream");
if (outputStream.CanWrite == false)
throw new ArgumentException("Cannot write to output stream");
object[] attributes;
attributes = o.GetType().GetCustomAttributes(typeof(NamespaceAttribute), true);
XmlWriterSettings writerSettings = new XmlWriterSettings();
writerSettings.Indent = true;
writerSettings.NewLineOnAttributes = true;
using (XmlWriter w = XmlWriter.Create(outputStream, writerSettings))
{
DataContractSerializer s = new DataContractSerializer(o.GetType());
s.WriteStartObject(w, o);
foreach (NamespaceAttribute ns in attributes)
w.WriteAttributeString("xmlns", ns.Prefix, null, ns.Uri);
// content
s.WriteObjectContent(w, o);
s.WriteEndObject(w);
}
}
}
I have struggled with this problem also. The solution I present below is not optimal IMHO but it works. Like Marc Gravell above, I suggest using XmlSerializer.
The trick is to add a field to your class that returns a XmlSerializerNamespaces object. This field must be decorated with a XmlNamespaceDeclarations attribute. In the constructor of your class, add namespaces as shown in the example below. In the xml below note that the root element is prefixed correctly as well as the someString element.
More info on XmlSerializerNamespaces
Schemas reference
[XmlRoot(Namespace="http://STPMonitor.myDomain.com")]
public class CFMessage : IQueueMessage<CFQueueItem>
{
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns;
[XmlAttribute("schemaLocation", Namespace=System.Xml.Schema.XmlSchema.InstanceNamespace)]
public string schemaLocation = "http://STPMonitor.myDomain.com/schemas/CFMessage.xsd";
[XmlAttribute("type")]
public string Type { get; set; }
[XmlAttribute("username")]
public string UserName { get; set; }
[XmlAttribute("somestring", Namespace = "http://someURI.com")]
public string SomeString = "Hello World";
public List<CFQueueItem> QueueItems { get; set; }
public CFMessage()
{
xmlns = new XmlSerializerNamespaces();
xmlns.Add("myDomain", "http://STPMonitor.myDomain.com");
xmlns.Add("xyz", "http://someURI.com");
}
}
<?xml version="1.0" encoding="utf-16"?>
<myDomain:CFMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xyz="http://someURI.com"
xsi:schemaLocation="http://STPMonitor.myDomain.com/schemas/CFMessage.xsd"
xyz:somestring="Hello World" type="JOIN" username="SJ-3-3008-1"
xmlns:myDomain="http://STPMonitor.myDomain.com" />
Add "http://www.w3.org/2001/XMLSchema" namespace by:
private static string DataContractSerialize(object obj)
{
StringWriter sw = new StringWriter();
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (XmlTextWriter xw = new XmlTextWriter(sw))
{
//serializer.WriteObject(xw, obj);
//
// Insert namespace for C# types
serializer.WriteStartObject(xw, obj);
xw.WriteAttributeString("xmlns", "x", null, "http://www.w3.org/2001/XMLSchema");
serializer.WriteObjectContent(xw, obj);
serializer.WriteEndObject(xw);
}
StringBuilder buffer = sw.GetStringBuilder();
return buffer.ToString();
}