I have created a REST Service which sends a response in XML. I have set the response format as XML and created the following Data Contracts:
[DataContract]
public class AuthorisationResult
{
[DataMember]
public string Status { get; set; }
[DataMember]
public Variable[] Variables { get; set; }
}
[DataContract]
public class Variable
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Type { get; set; }
}
This works ok however the output of the XML is not formatted as I need it. It is showing like this:
<Variables>
<Variable>
<Name>SomeName1</Name>
<Type>SomeType1</Type>
</Variable>
</Variables>
But I want to show it like this:
<Variables>
<Variable Name="SomeName1" Type="SomeType1"/>
</Variables>
Can anyone advise what I change to structure it how I want.
Just add XmlAttribute to the properties
[DataContract]
public class Variable
{
[DataMember, XmlAttribute]
public string Name { get; set; }
[DataMember, XmlAttribute]
public string Type { get; set; }
}
Related
I have following XML-Data:
<?xml version="1.0"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<LastChange>
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/RCS/">
<InstanceID val="0">
<RoomVolumes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=100"/>
<Volume channel="Master" val="100"/>
<Mute channel="Master" val="0"/>
<RoomMutes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=0"/>
</InstanceID>
</Event>
</LastChange>
</e:property>
</e:propertyset>
And here are my classes:
[XmlRoot("propertyset", Namespace = "urn:schemas-upnp-org:event-1-0")]
public class EventPropertySet
{
[XmlElement("property")]
public List<EventProperty> Properties { get; set; }
}
public class EventProperty
{
[XmlElement("LastChange")]
public string LastChange { get; set; }
[XmlElement("SinkProtocolInfo")]
public string SinkProtocolInfo { get; set; }
[XmlElement("IndexerStatus")]
public string IndexerStatus { get; set; }
[XmlElement("SystemUpdateID")]
public string SystemUpdateID { get; set; }
}
Now when I try to deserialize the XML-Data 'LastChange' is always 'null'.
When I modify the class 'EventProperty' like so:
public class EventProperty
{
[XmlElement("LastChange", Namespae = "")]
public string LastChange { get; set; }
[XmlElement("SinkProtocolInfo", Namespae = "")]
public string SinkProtocolInfo { get; set; }
[XmlElement("IndexerStatus", Namespae = "")]
public string IndexerStatus { get; set; }
[XmlElement("SystemUpdateID", Namespae = "")]
public string SystemUpdateID { get; set; }
}
The deserialization throws an exception:
XmlException: ReadElementContentAs() methods cannot be called on an element that has child elements. Line 1, position 103.
Any ideas what I should do?
Sorry, I found the problem. The data behind "LastChange" is normaly a parsed XML-Structure (like this:)
<LastChange><Event xmlns="urn:schemas-upnp-org:metadata-1-0/RCS/"><InstanceID val="0"><RoomVolumes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=100"/><Volume channel="Master" val="100"/><Mute channel="Master" val="0"/><RoomMutes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=0"/></InstanceID></Event></LastChange>
Now when I don't do the "DeParse" with WebUtility.HtmlDecode, everythings works fine.
I have following xml
<result>
<key accessMask="4294967295" type="Account" expires="">
<rowset name="characters" key="characterID" columns="characterID,characterName,corporationID,corporationName,allianceID,allianceName,factionID,factionName">
<row characterID="123" characterName="Sefa 123" corporationID="456" corporationName="Signal Cartel" allianceID="159" allianceName="Scouts" factionID="0" factionName=""/>
<row characterID="1234" characterName="Sefa 1234" corporationID="987" corporationName="Havos" allianceID="753" allianceName="Unlimited" factionID="0" factionName=""/>
</rowset>
</key>
</result>
And i have following Schema setup for deserializing this output.
[XmlRoot("result")]
public class ApiKeyInfo
{
[XmlElement("key")]
public Key Key { get; set; }
}
public class Key
{
[XmlAttribute("accessMask")]
public long AccessMask { get; set; }
[XmlAttribute("type")]
public string Type { get; set; }
[XmlElement("rowset")]
public List<AccountCharacter> Characters { get; set; }
}
public class AccountCharacter
{
[XmlAttribute("characterId")]
public long Id { get; set; }
[XmlAttribute("characterName")]
public string Name { get; set; }
[XmlAttribute("corporationID")]
public long CorpId { get; set; }
[XmlAttribute("corporationName")]
public string CorpName { get; set; }
[XmlAttribute("allianceID")]
public long AllianceId { get; set; }
[XmlAttribute("allianceName")]
public string AllianceName { get; set; }
[XmlAttribute("factionID")]
public long FactionId { get; set; }
[XmlAttribute("factionName")]
public string FactionName { get; set; }
}
Problem is, i can't deserialize character informations. Characters list is always containing 0 elements inside.
This:
[XmlElement("rowset")]
public List<AccountCharacter> Characters { get; set; }
Implies that you'll have a bunch of rowset elements, e.g:
<rowset characterID="123" characterName="Sefa 123" ...
Try this instead:
[XmlArray("rowset")]
[XmlArrayItem("row")]
public List<AccountCharacter> Characters { get; set; }
A useful tip for these sort of deserialisation problems is to try the process in reverse: create an object and serialise it and see what the XML looks like. It will likely give you some indication as to where your problem is.
See this fiddle for a working demo, it prints both row name values to the console.
Here's my XML:
<Events>
<Event>
<content_id>6442452774</content_id>
<content_title>Title of the event</content_title>
<content_html>
<Date>2015-11-18</Date>
<EventType>Events</EventType>
<Description>
<p>this is an "event"</p>
</Description>
<Speakers>speaker1 LLC<br />speaker2<br />Jspeaker3</Speakers>
<Time>5:30 - 6:00pm Registration<br />6:00 - 7:00pm Panel Discussion<br />7:00 - 8:00pm Networking Reception</Time>
<Where></Where>
<RegistrationInfo>Please contact events#events.com to register for this event.</RegistrationInfo>
<Registration>false</Registration>
</content_html>
<date_created>2015-10-24T14:24:12.333</date_created>
<folder_id>262</folder_id>
<content_teaser>this is the content "can you display it."</content_teaser>
<content_text>text of the vent "more text" a lot of text here </content_text>
<end_date>2015-11-19T21:35:00</end_date>
<content_type>1</content_type>
<template_id>43</template_id>
<content_status>A</content_status>
</Event>
<Event>.... Other events </Event>
<Events>
and here's are my classes:
public class Serializable_Events
{
[XmlElement("Event")]
public List<Serializable_Event> EventList = new List<Serializable_Event>();
}
public class Serializable_Event
{
[XmlElement("content_id")]
public string content_id { get; set; }
[XmlElement("content_title")]
public string content_title { get; set; }
[XmlElement("content_html")]
public Serializable_Event_ContentHTML ContentHTML { get; set; }
[XmlText]
public string content_teaser { get; set; }
[XmlElement("content_text")]
public string content_text { get; set; }
}
public class Serializable_Event_ContentHTML
{
[XmlElement("Date")]
public string Date { get; set; }
[XmlElement("EventType")]
public string EventType { get; set; }
[XmlElement("Description")]
public string Description { get; set; }
[XmlElement("Speakers")]
public string Speakers { get; set; }
[XmlElement("Time")]
public string Time { get; set; }
[XmlElement("Where")]
public string Where { get; set; }
[XmlElement("RegistrationInfo")]
public string RegistrationInfo { get; set; }
[XmlElement("Registration")]
public bool Registration { get; set; }
//ignored html tags
[XmlIgnore]
public string p { get; set; }
[XmlIgnore]
public string br { get; set; }
[XmlIgnore]
public string a { get; set; }
}
Implementation:
XmlSerializer ser = new XmlSerializer(typeof(Serializable_Events));
var data = (Serializable_Events)ser.Deserialize(new StreamReader(#"events.xml"));
My problem is that some attributes are null and some are not (see the screenshot)
The ones that are null, like <Description> are due to malformed
XML.
You are storing HMTL directly in XML with text all over the place, and the serializer is not expecting that; further you are telling the serializer to ignore HTML tags using XmlIgnore which is intended for XML tags with properly formed XML. That's a wrong use of XmlIgnore
All XML which contains non-XML mark-up should be wrapped in CDATA sections; this will solve your problem. Further, you can remove all of the XmlIgnore code as well since it's not needed.
Your XML should look like this:
<Events>
<Event>
<content_id>6442452774</content_id>
<content_title>Title of the event</content_title>
<content_html>
<Date>2015-11-18</Date>
<EventType>Events</EventType>
<Description>
<![CDATA[<p>this is an ""event""</p>]]>
</Description>
<Speakers>
<![CDATA[speaker1 LLC<br />speaker2<br />Jspeaker3]]>
</Speakers>
<Time>
<![CDATA[5:30 - 6:00pm Registration<br />6:00 - 7:00pm Panel Discussion<br />7:00 - 8:00pm Networking Reception]]>
</Time>
<Where></Where>
<RegistrationInfo>
<![CDATA[Please contact <a href='mailto:events#events.com'>events#events.com</a> to register for this event.]]>
</RegistrationInfo>
<Registration>false</Registration>
</content_html>
<date_created>2015-10-24T14:24:12.333</date_created>
<folder_id>262</folder_id>
<content_teaser>this is the content 'can you display it.'</content_teaser>
<content_text>text of the vent 'more text' a lot of text here </content_text>
<end_date>2015-11-19T21:35:00</end_date>
<content_type>1</content_type>
<template_id>43</template_id>
<content_status>A</content_status>
</Event>
</Events>"
I have XML-based config for application shortcuts bindings. i need to parse it.
<ShortcutBinding>
<ShortcutHandler Name ="Retail.Application.Documents.Outcome.Presentation.OutcomePresenter">
<Shortcut Name="EditHeader">
<Key>CTRL</Key>
<Key>F4</Key>
</Shortcut>
<Shortcut Name="EditItem">
<Key>F4</Key>
</Shortcut>
</ShortcutHandler>
</ShortcutBinding>
I know that .Net has attributes for deserializing XML into objects.
Can anyone write complete example for such deserialization, using attributes.
public class ShortcutBinding
{
public ShortcutHandler ShortcutHandler { get; set; }
}
public class ShortcutHandler
{
[XmlAttribute]
public string Name { get; set; }
[XmlElement("Shortcut")]
public List<Shortcut> Shortcuts { get; set; }
}
public class Shortcut
{
[XmlAttribute]
public string Name { get; set; }
[XmlElement("Key")]
public List<string> Keys { get; set; }
}
Deserializing:
XmlSerializer serializer = new XmlSerializer(typeof(ShortcutBinding));
var binding = (ShortcutBinding)serializer.Deserialize(XmlReader.Create(path));
I want to deserialize the following xml into my class, i can't change the xml because it commes from a device over tcp/ip.
<?xml version="1.0" encoding="utf-8"?>
<CONTACTINFORMATION UID="1234">
<LoginId><![CDATA[1234]]></LoginId>
<ContactId><![CDATA[2134]]></ContactId>
<ContactType>CCININTERN</ContactType>
<Status>CONVERSATION</Status>
<From><![CDATA[123]]></From>
<To><![CDATA[123]]></To>
<WaitTime><![CDATA[123]]></WaitTime>
<ContactPropertySummary>
<ContactProperty>
<Name><![CDATA[13]]></Name>
<Value><![CDATA[13]]></Value>
<Hidden>NO</Hidden>
<Url><![CDATA[13]]></Url>
</ContactProperty>
</ContactPropertySummary>
<SkillSummary>
<Skill>
<Name><![CDATA[123]]></Name>
<Mandatory>YES</Mandatory>
</Skill>
<Skill>
<Name><![CDATA[124]]></Name>
<Mandatory>YES</Mandatory>
</Skill>
</SkillSummary>
<ContactCodeSummary>
<ContactCode>
<Id>123</Id>
<Hidden>NO</Hidden>
<Assigned>YES</Assigned>
</ContactCode>
</ContactCodeSummary>
<GroupSummary>
<Group>
<Name><![CDATA[123]]></Name>
<Mandatory>YES</Mandatory>
</Group>
</GroupSummary>
<PreviousAgent><![CDATA[2]]></PreviousAgent>
<ScratchPadId><![CDATA[2]]></ScratchPadId>
<ScratchPadData><![CDATA[2]]></ScratchPadData>
<FaxSpecific>
<NbrOfPages>2</NbrOfPages>
</FaxSpecific>
</CONTACTINFORMATION>
My class:
[Serializable]
[XmlRoot("CONTACTINFORMATION")]
public class Contact
{
#region :: PROPERTIES ::
public string LoginId { get; set; }
public string ContactId { get; set; }
public ContactType ContactType { get; set; }
public ContactStatus Status { get; set; }
[XmlElement("From")]
public string ContactFrom { get; set; }
[XmlElement("To")]
public string ContactTo { get; set; }
public int WaitTime { get; set; }
[XmlElement("SkillSummary", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[XmlArray("Skill")]
//[XmlElement("SkillSummary", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Skill[] Skills { get; set; }
[XmlArray("ContactPropertySummary")]
public ContactProperty[] Properties { get; set; }
[XmlArray("GroupSummary", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[XmlArrayItem("Group", typeof(Group), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Group[] Groups { get; set; }
}
The arry of skills has 2 skills, after deserializing there is only 1 skill in the arry, the groups and properties array is null...
What i'm doing wrong?
You should properly decorate array properties with XmlArray and XmlArrayItem attributes. For e.g. for skills property you are using XmlElement with XmlArray which is not permitted.
[XmlArrayItem("Skill", typeof(Skill), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[XmlArray("SkillSummary", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Skill[] Skills
{
get;
set;
}
[XmlArray("ContactPropertySummary")]
[XmlArrayItem("ContactProperty", typeof(ContactProperty), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ContactProperty[] Properties
{
get;
set;
}
[XmlArray("GroupSummary", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[XmlArrayItem("Group", typeof(Group), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Group[] Groups
{
get;
set;
}
Make Sure that xmlArrayItem 'types' have proper read/write properties
public class Skill
{
public string Name
{
get;
set;
}
public string Mandatory
{
get;
set;
}
}
I recommend you to provide as much information to the XMLSerializer, through attributes, as you can.
You don't seem to be too off the mark. Using the above definitions I was able to successfully deserialize the XML you provided.
Start by defining a class Skill and then using this class in your Contract class.
// We're going to define a class called Skill
[Serializable()]
public class Skill
{
[System.Xml.Serialization.XmlElement("Name")]
public string Name { get; set; }
[System.Xml.Serialization.XmlElement("Mandatory")]
public string Mandatory { get; set; }
}
[Serializable]
[XmlRoot("CONTACTINFORMATION")]
public class Contact
{
// ...... Rest of your elements
[XmlArray("SkillSummary")]
[XmlArrayItem("Skill", typeof(Skill))]
public Skills[] Skill { get; set; }
}
Please do the same for Groups and Properties as well.