How should I get the <site-standard-profile-request> child element to deserialize correctly so that it does not show up as null?
The deserialization process is perfect; I just need to get the child element <site-standard-profile-request> to serialize as well.
//<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
//- <person>
// <first-name>Storefront</first-name>
// <last-name>Doors</last-name>
// <headline>CEO at StorefrontDoors.NET</headline>
//- <site-standard-profile-request>
// <url>http://www.linkedin.com/profile?viewProfile=&key=147482099&authToken=-Igm&authType=name&trk=api*a216630*s224617*</url>
// </site-standard-profile-request>
// </person>
[XmlRoot("person")]
[Serializable()]
public class LinkedIn
{
[XmlElement("first-name")]
public string FirstName { get; set; }
[XmlElement("last-name")]
public string LastName { get; set; }
[XmlElement("headline")]
public string Headline { get; set; }
public string URL { get; set; }
}
string profile = oauth.APIWebRequest("GET", "https://api.linkedin.com/v1/people/~", null);
//
LinkedIn lkIn = null;
BufferedStream stream = new BufferedStream(new MemoryStream());
stream.Write(Encoding.ASCII.GetBytes(profile), 0, profile.Length);
stream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(stream);
XmlSerializer serializer = new XmlSerializer(typeof(LinkedIn));
lkIn = (LinkedIn)serializer.Deserialize(sr);
stream.Close();
You'll need another serializable class with just the url as a property. Eg,
[XmlRoot("site-standard-profile-request")]
[Serializable()]
public class StandardProfile
{
public string url { get;set;}
}
And then your existing class should use it, something like
[XmlRoot("person")]
[Serializable()]
public class LinkedIn
{
[XmlElement("first-name")]
public string FirstName { get; set; }
[XmlElement("last-name")]
public string LastName { get; set; }
[XmlElement("headline")]
public string Headline { get; set; }
public StandardProfile Profile { get;set; }
}
I haven't tested this code, but should be pretty close.
Hope that helps.
Related
I have this simple xml that I just can't deserialise to an object, there are something wrong with my model classes. I just Receive an empty object.
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
\n<response>
\n<lst name=\"responseHeader\">
<int name=\"status\">0</int>
<int name=\"QTime\">20596</int>
</lst>\n
</response>\n"
i serialize like this:
var x = result.Content;
XmlSerializer serializer = new XmlSerializer(typeof(response));
StringReader rdr = new StringReader(x);
response resultingMessage =
(response)serializer.Deserialize(rdr);
and my model classes look like:
[XmlType("response")]
public class response
{
[XmlElement("responseHeader")]
public string Name { get; set; }
public List<lst> Lst { get; set; }
}
public class lst
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("int")]
public List<Int> Int { get; set; }
}
public class Int
{
[XmlElement("status")]
public int status { get; set; }
[XmlElement("QTime")]
public int QTime { get; set; }
}
Couple things to be corrected.
You need to clean the Xml
XmlSerializer serializer = new XmlSerializer(typeof(response));
StringReader rdr = new StringReader(xmlString.Replace(#"\n",String.Empty).Replace(#"\'","'"));
response resultingMessage =
(response)serializer.Deserialize(rdr);
Secondly, You data structure require some changes. For example, response doesn't require a name. It needs to be part of lst. Also it is an attribute, not an element. Hence needs to be decorated with [XmlAttribute]
[XmlType("response")]
public class response
{
[XmlElement("lst")]
public List<lst> Lst { get; set; }
}
public class lst
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("int")]
public List<Int> Int { get; set; }
}
public class Int
{
[XmlAttribute(AttributeName="name")]
public string Name { get; set; }
[XmlText]
public string Text { get; set; }
}
Output
try like this,
/*
var x = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<response>\n<lst name=\"responseHeader\"><int name=\"status\">0</int><int name=\"QTime\">20596</int></lst>\n</response>\n";
*/
var x = result.Content;
x= x.Replace("\\n", string.Empty).Replace("\\", string.Empty);
XmlSerializer serializer = new XmlSerializer(typeof(response));
StringReader rdr = new StringReader(x);
response resultingMessage =
(response)serializer.Deserialize(rdr);
sometimes extra characters can cause the conversion issue.
I am having issues creating the schema below...
<DocumentProperties>
<Document>
<Properties>
<propertyName>CNumber</propertyName>
<propertyValue>00645007803</propertyValue>
</Properties>
<targetFolder>\12345678\00645007803\</targetFolder>
</Document>
<Document>
<Properties>
<propertyName>CNumber</propertyName>
<propertyValue>00645007804</propertyValue>
</Properties>
<targetFolder>\12345678\00645007804\</targetFolder>
</Document>
</DocumentProperties>
I created the following classes to do this
public class DocumentProperties
{
public DocumentProperties()
{
Document = new List<Document>();
}
public List<Document> Document { get; set; }
}
public class Document
{
public Document()
{
Properties = new List<Properties>();
}
public List<Properties> Properties { get; set; }
public string targetFolder { get; set; }
}
public class Properties
{
public string propertyName { get; set; }
public string propertyValue { get; set; }
}
public class RetrieveMultipleDocumentsRequest
{
public SystemProperty SystemProperty { get; set; }
public RequestProperty RequestProperty { get; set; }
public DocumentProperties DocumentProperties { get; set; }
}
The output I am getting is "Document" and "Properties" twice as a parent child of each other. How do I resolve this?
Output from my classes
<DocumentProperties>
<Document>
<Document>
<Properties>
<Properties>
<propertyName>DizzzyGelespe</propertyName>
<propertyValue>8E077A60</propertyValue>
</Properties>
<Properties />
</Properties>
<targetFolder>C:\BXml\TargetFolder\</targetFolder>
</Document>
</Document>
</DocumentProperties>
Code that is generating the output:
public string Serialize(RetrieveMultipleDocumentsRequest details)
{
XmlSerializer serializer = new XmlSerializer(typeof(RetrieveMultipleDocumentsRequest));
using(StringWriter textWriter = new StringWriter())
{
serializer.Serialize(textWriter, details);
return textWriter.ToString();
}
}
You will need to annotate your object model as shown below in order to change the default serialization behavior. This application of the XmlElement attribute will prevent emiting out the parent tag based upon the encountered property and instead only emit out the containing data.
public class DocumentProperties
{
public DocumentProperties()
{
Document = new List<Document>();
}
[XmlElement("Document")]
public List<Document> Document { get; set; }
}
public class Document
{
public Document()
{
Properties = new List<Properties>();
}
[XmlElement("Properties")]
public List<Properties> Properties { get; set; }
public string targetFolder { get; set; }
}
Apparently your naming convention confused the XML serializer a bit. Just explicitly decorate the elements as below and it should work fine:
public class DocumentProperties
{
public DocumentProperties()
{
Document = new List<Document>();
}
[XmlElement("Document")]
public List<Document> Document { get; set; }
}
public class Document
{
public Document()
{
Properties = new List<Properties>();
}
[XmlElement("Properties")]
public List<Properties> Properties { get; set; }
public string targetFolder { get; set; }
}
Your problem here is with naming.
A list of documents should be called "documents" not "document", same goes for properties.
If you make these naming changes then you will see that your XML output is correct and makes sense.
I'm attempting to deserialize this XML file into an object
<?xml version="1.0" encoding="utf-8" ?>
<rules version="3">
<emie>
<domain>msdn.microsoft.com</domain>
<domain exclude="false">
bing.com
<path exclude="true">images</path>
</domain>
<domain exclude="true">
news.msn.com
<path exclude="false">pop-culture</path>
</domain>
<domain>timecard</domain>
<domain>tar</domain>
</emie>
</rules>
I have my objects laid out like so
[XmlRoot("rules")]
public class Rules {
[XmlAttribute("version")]
public string Version { get; set; }
[XmlElement("emie")]
public EMIE EMIE { get; set; }
}
public class EMIE {
[XmlArrayItem("Domain")]
public List<Domain> Domains { get; set; }
}
public class Domain {
[XmlAttribute("exclude")]
public bool Exclude { get; set; }
[XmlText]
public string Value { get; set; }
[XmlArrayItem("Path")]
public List<Path> Paths { get; set; }
}
public class Path {
[XmlAttribute]
public bool Exclude { get; set; }
[XmlText]
public string Value { get; set; }
}
And am using this code to deserialize it
static void Main(string[] args) {
XmlSerializer serializer = new XmlSerializer(typeof(Rules));
using (FileStream stream = new FileStream("EM.xml", FileMode.Open)) {
Rules xml = (Rules)serializer.Deserialize(stream);
foreach (Domain d in xml.EMIE.Domains) {
Console.WriteLine(d.Value);
foreach (EnterpriseModeModel.Path p in d.Paths) {
Console.WriteLine(p.Value);
}
}
}
Console.ReadLine();
}
However, my rules.EMIE.Domains object is always empty. When I debug I can see my stream object has a length so it's properly picking up the data in the file but it never fills up the object like I expect it to.
Change the declaration of EMIE as follows
public class EMIE
{
[XmlElement("domain")]
public List<Domain> Domains { get; set; }
}
I have one class Person and it has some public properties . Now I want to serialize person class but with some selected properties only. This can be achieve by making that property private but I don't want to change any property as private.
If its not possible using serialisation then, what is another way to create xml doc for object with selected properties only.
Note: All properties must be public.
class Program
{
static void Main(string[] args)
{
Person person = new Person();
using (MemoryStream memoryStream = new MemoryStream())
{
XmlSerializer xmlSerializer = new XmlSerializer(person.GetType());
xmlSerializer.Serialize(memoryStream, person);
using (FileStream fileStream = File.Create("C://Output.xml"))
{
memoryStream.WriteTo(fileStream);
fileStream.Close();
}
memoryStream.Close();
}
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public double Salary { get; set; }
public Person()
{
Id = 1;
Name = "Sam";
Salary = 50000.00;
}
}
Current Output
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>1</Id>
<Name>Sam</Name>
<Salary>50000</Salary>
</Person>
Expected Output
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Salary>50000</Salary>
</Person>
You could use an XmlIgnore attribute..
public class Person
{
[XmlIgnore]
public int Id { get; set; }
[XmlIgnore]
public string Name { get; set; }
public double Salary { get; set; }
public Person()
{
Id = 1;
Name = "Sam";
Salary = 50000.00;
}
}
See this
can you give a try to below code and just use XmlIgnore attribute on he properties which you not require :-
[XmlIgnore]
public int Id { get; set; }
[XmlIgnore]
public string Name { get; set; }
public double Salary { get; set; }
This is the xml stream:
<?xml version="1.0" encoding="utf-8" ?>
<historydetails>
<taskEvent>
<eventtype>Transitions</eventtype>
<historyevent>Task moved</historyevent>
<details>From 'Requested' to 'In Validation'</details>
<author>NAme</author>
<entrydate>01 Jul 13, 11:34</entrydate>
<historyid>2620</historyid>
</taskEvent>
<taskEvent>
<eventtype>Updates</eventtype>
<historyevent>Subtask marked done</historyevent>
<details>Subtask: visualise status and versions</details>
<author>NAme2</author>
<entrydate>21 Jun 13, 10:16</entrydate>
<historyid>2588</historyid>
</taskEvent>
</historydetails>
The corresponding classes look like this:
public class historydetails
{
[XmlElement("taskEvent")]
List<taskEvent> eventList = new List<taskEvent>();
}
public class taskEvent
{
string eventtype { get; set; }
string historyevent { get; set; }
string details { get; set; }
string author { get; set; }
string entrydate { get; set; }
string historyid { get; set; }
}
the code to deserialise the xml (the string replacement contains the xml code):
XmlSerializer deserializer = new XmlSerializer(typeof(historydetails));
object obj = obj = deserializer.Deserialize(stringToStream(replacement));
historydetails XmlData = (historydetails)obj;
The method stringToStream
private MemoryStream stringToStream(string input)
{
byte[] byteArray = Encoding.ASCII.GetBytes(input);
MemoryStream stream = new MemoryStream(byteArray);
return stream;
}
The result that i get is as following:
The object XmlData is made and there is a list of taskEvents.
The problem is in the list itself: it is empty...
You have to make the members public
public class historydetails
{
[XmlElement("taskEvent")]
public List<taskEvent> eventList = new List<taskEvent>();
}
public class taskEvent
{
public string eventtype { get; set; }
public string historyevent { get; set; }
public string details { get; set; }
public string author { get; set; }
public string entrydate { get; set; }
public string historyid { get; set; }
}
As an aside, for future reference (with Visual Studio 2012 or the WebEssentials plugin), one of the easiest way to create the classes based on some sample XML content data is to copy it into the clipboard and then use the built-in VS function: EDIT - > Paste Special -> Paste XML As Classes into a new class file.
It leaves less space for errors like the one you encountered and
It's fast, you'll have your classes ready in a few seconds