xml Serialization and Deserialization (hide one node header) - c#

I have an XML file and I need to deserialize it. Without bypassing all the nodes, just deserilizing the XML file to an object.
Is it possible to hide from the result ActionGetSiteResultData or only one way
use custom serialization/deserialization?
Classes:
// root
public Result Result { get; set; }
// rows
public class Result
{
public List<ResultData> Data { get; set; }
}
//item
public class ResultData
{
[XmlElement(ElementName = "gen_info")]
public GenInfo GenInfo { get; set; }
[XmlElement(ElementName = "hosting")]
public Hosting Hosting { get; set; }
}
Result:
<Result>
<Id>1</Id>
<Data>
<ResultData> <--- REMOVE THIS
<gen_info>
<ascii-name>sadsad</ascii-name>
</gen_info>
<hosting/>
</ResultData> <--- REMOVE THIS
</Data>
</Result>
Need:
<Result>
<Id>1</Id>
<Data>
<gen_info>
<ascii-name>sadsad</ascii-name>
</gen_info>
<hosting/>
</Data>
</Result>
<Result>
<Id>2</Id>
<Data>
<gen_info>
<ascii-name>sadsad2</ascii-name>
</gen_info>
<hosting/>
</Data>
</Result>

This should do but is verbose. Try [XmlElement(ElementName = "gen_info")] on ResultData property first, if it doesn't work:
public class Result
{
[XmlIgnore]
public List<ResultData> Data { get; set; }
[XmlElement(ElementName = "gen_info")]
public ResultData[] __XmlSerializedData{
get{ return Data.ToArray();}
set{ Data = new List<ResultData>(value);}
}
}

Related

Cannot deserialize sub-elements to list of objects

I am having problems serializing elements of an XML to a list of objects.
This is the XML:
<result>
<stats>
<numitemsfound>1451</numitemsfound>
<startfrom>0</startfrom>
</stats>
<items>
<item>
<id>1</id>
<markedfordeletion>0</markedfordeletion>
<thumbsrc>
</thumbsrc>
<thumbsrclarge>
</thumbsrclarge>
...
<datasource>65</datasource>
<data>
<amount>100</amount>
<kj>389</kj>
<kcal>92.91</kcal>
<fat_gram>0.2</fat_gram>
<fat_sat_gram>-1</fat_sat_gram>
<kh_gram>20.03</kh_gram>
</data>
<servings>
<serving>
<serving_id>386</serving_id>
<weight_gram>150</weight_gram>
</serving>
</servings>
</item>
</result>
The classes I prepared for serialization are
[XmlType("item")]
public class Item
{
[XmlAttribute("id")]
public string id { get; set; }
[XmlAttribute("markedfordeletion")]
public string markedfordeletion { get; set; }
...
[XmlAttribute("datasource")]
public string datasource { get; set; }
[XmlElement("data")]
public Data data { get; set; }
[XmlElement("servings")]
public List<Serving> servings { get; set; }
}
}
This is how I try to serialize the xml
public void ParseSearch(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>), new XmlRootAttribute("item"));
StringReader stringReader = new StringReader(xml);
var productList = (List<Item>)serializer.Deserialize(stringReader);
}
But I get the error ----> System.InvalidOperationException : <result xmlns=''> was not expected. Can you please help me solve this problem?
You have to use a serializer which serializes an instance of result, not of type List:
XmlSerializer serializer = new XmlSerializer(typeof(Result), new XmlRootAttribute("result")); //whatever `Result` actually is as type).
You canĀ“t serialize and de-serialize just parts of a document, either the whole one or nothing at all.
So you need a root-type:
[XmlRoot("result")]
public class Result
{
public Stats Stats {get; set;}
[XmlArray("items")]
[XmlArrayItem("item")]
public List<Item> Items { get; set; }
}

XmlSerializer Deserializing List Without namespace

Trying to deserialize List.
Im getting the following error:
System.InvalidOperationException: There is an error in XML document
(1, 2). ---> System.InvalidOperationException: was not expected.
Saw other quesitons like : {"<user xmlns=''> was not expected.} Deserializing Twitter XML but this does not solve my problem either.
This is an Xml Sample
<authorizations>
<id>111</id>
<name>Name 1</name>
<Lists>
<List>
<id>1</id>
<id>2</id>
</List>
</Lists>
</authorizations>
<authorizations>
<id>222</id>
<name>Name 2</name>
<List />
</authorizations>
<authorizations>
<id>333</id>
<name>Name 3</name>
<List />
</authorizations>
The class are created as follow:
public class Authorization
{
[XmlElement("id")]
public string Id{ get; set; }
[XmlElement("name")]
public string Name{ get; set; }
[XmlArray("Lists")]
[XmlArrayItem("List")]
public List[] Items{ get; set; }
}
public class List
{
[XmlElement("id")]
public string Id{ get; set; }
}
public class AuthorizationList
{
[XmlArray("authorizations")]
public Authorization Authorizations{ get; set; }
}
Have tried changing the list to XmlArray, XmlArrayItem or Element. but still get the same error when I deserialize.
Deserializing Code Sample:
public static T FromXml<T>(string xmlString)
{
T obj = default(T);
if (!string.IsNullOrWhiteSpace(xmlString))
{
using (var stringReader = new StringReader(xmlString))
{
var xmlSerializer = new XmlSerializer(typeof(T));
obj = (T)xmlSerializer.Deserialize(stringReader);
}
}
return obj;
}
This is ALL premised on the assumption that you have minimal control over the xml and don't have the luxury of changing that too much. As others have noted, it is not well-formed. Here is one way to get serialization to work with minimal changes to your XML and types. First, get rid of your AuthorizationList type and assign an XmlType attribute to your Authorization type (this step serves to simply pluralize the name to match how your XML has it).
[XmlType("authorizations")]
public class Authorization { ... }
public class List { ... }
Wrap your XML in the following root element:
<ArrayOfAuthorizations>
...
</ArrayOfAuthorizations>
The XML now represents a list of "authorizations" so to deserialize is just this:
List<Authorization> l = FromXml<List<Authorization>>(xml);
Another Solution:
Change the Authorizations member to be of type Authorization[] (array type rather than singular) and to have an XmlElement attribute (not XmlArray). Apply the XmlType attribute to the Authorization (as with the above solution this is to match the xml since it has the pluralized name for each array element).
[XmlType("authorizations")]
public class Authorization
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlArray("Lists")]
[XmlArrayItem("List")]
public List[] Items { get; set; }
}
public class List
{
[XmlElement("id")]
public string Id { get; set; }
}
public class AuthorizationList
{
[XmlElement("authorizations")]
public Authorization[] Authorizations { get; set; }
}
Like before, you need to wrap your XML with the matching 'AuthorizationList' root element:
<AuthorizationList>
...
</AuthorizationList>
Then you deserialize instance of your AuthorizationList type rather that List<T> as with the previous solution.
AuthorizationList l = FromXml<AuthorizationList>(xml);
Note that the root XML element will also need to match that type name also.
<AuthorizationList>
<authorizations>
<id>111</id>
<name>Name 1</name>
<Lists>
<List>
<id>1</id>
<id>2</id>
</List>
</Lists>
</authorizations>
<authorizations>
<id>222</id>
<name>Name 2</name>
<List />
</authorizations>
<authorizations>
<id>333</id>
<name>Name 3</name>
<List />
</authorizations>
</AuthorizationList>

How to read XML elements c# (sample code provided)

I have the following XML sample that I want to read the data. I only provided one "project" element but this can have many "project" inside the "projects" root.
<?xml version="1.0" encoding="utf-8"?>
<projects>
<project>
<details>
<projectName><![CDATA[CxWtGZxYT]]></projectName>
<uniqueID>Pt144</uniqueID>
<collaboratingList>
<collaboratingOrganisation id="5318" value="EpCyxCv RvGxrXAYXGpA xCxWtGZxYT"/>
<collaboratingOrganisation id="0000" value="EpCyxCv RvGxrXAYXGpA xCxWtGZxYTd"/>
</collaboratingList>
<researchOutputList>
<item>
<pubDate>2014-02-04T00:00:00+00:00</pubDate>
<title><![CDATA[rGDEZ]]></title>
<link>link</link>
<guid>guid</guid>
<description><![CDATA[uGDB BDstA rGDEZ]]></description>
</item>
<item>
<pubDate>2015-08-04T00:00:00+00:00</pubDate>
<title><![CDATA[AERx CApCYZ.]]></title>
<link>link</link>
<guid>guid</guid>
<description><![CDATA[vwtpY]]></description>
</item>
</researchOutputList>
</details>
</project>
</projects>
I can read the <projectName> and <uniqueId> but cannot <researchOutputList> and <collaboratingList>. I am not sure what I am missing or if my XML structure is correct. My codes below:
[Serializable]
[XmlRoot("projects")]
public class BulkProjectRoot
{
public BulkProjectRoot()
{
BulkProjectDetails = new List<BulkProjectData>();
}
[XmlArray("project")]
[XmlArrayItem("details")]
public List<BulkProjectData> BulkProjectDetails { get; set; }
}
[Serializable]
[XmlRoot("details")]
public class BulkProjectData
{
public BulkProjectData()
{
ProjectResearches = new List<ProjectResearchOutputs>();
}
[XmlElement("projectName")]
public string Name { get; set; }
[XmlElement("uniqueID")]
public string ProjectUniqueId { get; set; }
[XmlElement("researchOutputList")]
public List<ProjectResearchOutputs> ProjectResearches { get; set; }
}
[Serializable]
[XmlRoot("researchOutputList")]
public class ProjectResearchOutputs
{
public ProjectResearchOutputs()
{
ResearchItemsList = new List<ResearchOutputItems>();
}
[XmlElement("item")]
public List<ResearchOutputItems> ResearchItemsList { get; set; }
}
[Serializable]
[XmlRoot("item")]
public class ResearchOutputItems
{
[XmlElement("pubDate")]
public DateTime? PublishDate { get; set; }
[XmlElement("title")]
public string ResearchTitle { get; set; }
[XmlElement("link")]
public string ResearchLink { get; set; }
[XmlElement("guid")]
public string ResearchGuid { get; set; }
[XmlElement("description")]
public string ResearchDescription { get; set; }
}
The reasearchlist deserializes fine with Linqpad, but you are missing the collaboration information in your BulkProjectData class.
void Main()
{
var xml = #"<?xml version=""1.0"" encoding=""utf - 8""?>
<projects>
<project>
<details>
<projectName><![CDATA[CxWtGZxYT]]></projectName>
<uniqueID> Pt144 </uniqueID>
<collaboratingList>
<collaboratingOrganisation id = ""5318"" value = ""EpCyxCv RvGxrXAYXGpA xCxWtGZxYT"" />
<collaboratingOrganisation id = ""0000"" value = ""EpCyxCv RvGxrXAYXGpA xCxWtGZxYTd"" />
</collaboratingList>
<researchOutputList>
<item>
<pubDate>2014-02-04T00:00:00+00:00</pubDate>
<title><![CDATA[rGDEZ]]></title>
<link> link </link>
<guid> guid </guid>
<description><![CDATA[uGDB BDstA rGDEZ]]></description>
</item>
<item>
<pubDate>2015-08-04T00:00:00+00:00</pubDate>
<title><![CDATA[AERx CApCYZ.]]></title>
<link> link </link>
<guid> guid </guid>
<description><![CDATA[vwtpY]]></description>
</item>
</researchOutputList>
</details>
</project>
</projects>";
var serializer = new XmlSerializer(typeof(BulkProjectRoot));
var result = (BulkProjectRoot)serializer.Deserialize(new StringReader(xml));
result.Dump();
Jsut make this change -
[Serializable]
[XmlRoot("details")]
public class BulkProjectData
{
public BulkProjectData()
{
// Not a list
ProjectResearches = new ProjectResearchOutputs();
}
[XmlElement("projectName")]
public string Name { get; set; }
[XmlElement("uniqueID")]
public string ProjectUniqueId { get; set; }
[XmlElement("researchOutputList")]
public ProjectResearchOutputs ProjectResearches { get; set; }
}

Writing into xml with more than one lines

I am developing a c# application.
I need to write company-product details in this form. One company may have more than one product and one xml file may contain only 1 company. So one xml file for every company.
<?xml version="1.0" encoding="utf-8" ?>
<list>
<CompanyName>Test</CompanyName>
<CompanyID>TestID</CompanyID>
<Product>
<ProductName>Prod</ProductName>
<ProductID>ProdID</ProductID>
<Expire>10.10.2010</Expire>
</Product>
<Product>
<ProductName>Prod2</ProductName>
<ProductID>ProdID2</ProductID>
<Expire>11.10.2010</Expire>
</Product>
<Product>
<ProductName>Prod3</ProductName>
<ProductID>ProdID3</ProductID>
<Expire>12.10.2010</Expire>
</Product>
</list>
How can i make one xml file to have 3 attributes in c#?
I would appreciate your helps.
Regards
If you are asking how to write an xml file in C# then you have write a class provide xml attributes to class and its properties, and then serialize the class.
Instance of the class with all its data will be serialized to xml:
Here is an example in your situation.
[XmlType(TypeName = "CompanyXml")]
public class Company : ISerializable
{
[XmlElement("Product")]
public List<Product> ListProduct { get; set; }
[XmlElement("CompanyName")]
public string CompanyName { get; set; }
[XmlElement("CompanyID")]
public string CompanyID { get; set; }
}
Product class looks like:
[XmlType(TypeName = "Product")]
public class Product : ISerializable
{
[XmlElement("ProductName")]
public string ProductName { get; set; }
[XmlElement("ProductID")]
public string ProductID { get; set; }
[XmlElement("Expires")]
public string Expires { get; set; }
}
Serialization code could follow as:
using (StringWriter stringWriter = new StringWriter())
{
XmlSerializer serializer = new XmlSerializer(typeof(Company));
serializer.Serialize(stringWriter, companyInstance);
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(stringWriter.ToString());
}

Problem with Serialization/Deserialization an XML containing CDATA attribute

I need to deserialize/serialize the xml file below:
<items att1="val">
<item att1="image1.jpg">
<![CDATA[<strong>Image 1</strong>]]>
</item>
<item att1="image2.jpg">
<![CDATA[<strong>Image 2</strong>]]>
</item>
</items>
my C# classes:
[Serializable]
[XmlRoot("items")]
public class RootClass
{
[XmlAttribute("att1")]
public string Att1 {set; get;}
[XmlElement("item")]
public Item[] ArrayOfItem {get; set;}
}
[Serializable]
public class Item
{
[XmlAttribute("att1")]
public string Att1 { get; set; }
[XmlText]
public string Content { get; set; }
}
and everything works almost perfect but after deserialization in place
<![CDATA[<strong>Image 1</strong>]]>
I have
<strong>Image 1</strong>
I was trying to use XmlCDataSection as type for Content property but this type is not allowed with XmlText attribute. Unfortunately I can't change XML structure.
How can I solve this issue?
this should help
private string content;
[XmlText]
public string Content
{
get { return content; }
set { content = XElement.Parse(value).Value; }
}
First declare a property as XmlCDataSection
public XmlCDataSection ProjectXml { get; set; }
in this case projectXml is a string xml
ProjectXml = new XmlDocument().CreateCDataSection(projectXml);
when you serialize your message you will have your nice format (notice )
<?xml version="1.0" encoding="utf-16"?>
<MessageBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Message_ProjectStatusChanged">
<ID>131</ID>
<HandlerName>Plugin</HandlerName>
<NumRetries>0</NumRetries>
<TriggerXml><![CDATA[<?xml version="1.0" encoding="utf-8"?><TmData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="9.0.0" Date="2012-01-31T15:46:02.6003105" Format="1" AppVersion="10.2.0" Culture="en-US" UserID="0" UserRole=""><PROJECT></PROJECT></TmData>]]></TriggerXml>
<MessageCreatedDate>2012-01-31T20:28:52.4843092Z</MessageCreatedDate>
<MessageStatus>0</MessageStatus>
<ProjectId>0</ProjectId>
<UserGUID>8CDF581E44F54E8BAD60A4FAA8418070</UserGUID>
<ProjectGUID>5E82456F42DC46DEBA07F114F647E969</ProjectGUID>
<PriorStatus>0</PriorStatus>
<NewStatus>3</NewStatus>
<ActionDate>0001-01-01T00:00:00</ActionDate>
</MessageBase>
Most of the solutions presented in StackOverflow works only for Serialization, and not Deserialization. This one will do the job, and if you need to get/set the value from your code, use the extra property PriceUrlByString that I added.
private XmlNode _priceUrl;
[XmlElement("price_url")]
public XmlNode PriceUrl
{
get
{
return _priceUrl;
}
set
{
_priceUrl = value;
}
}
[XmlIgnore]
public string PriceUrlByString
{
get
{
// Retrieves the content of the encapsulated CDATA
return _priceUrl.Value;
}
set
{
// Encapsulate in a CDATA XmlNode
XmlDocument xmlDocument = new XmlDocument();
this._priceUrl = xmlDocument.CreateCDataSection(value);
}
}

Categories