I'm doing a C# project and I have an object encoded in XML; an example instance would be:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Entity Type="StartRunTestSetResponse">
<Fields>
<Field Name="SuccessStaus">
<Value>2</Value>
</Field>
<Field Name="info">
<Value></Value>
</Field>
</Fields>
</Entity>
I need the attribute information because it is a necessity in the Key-Value pairs' the object has.
My deserialization grammar looks like this:
[DataContract(Name="Entity", Namespace="")]
[XmlSerializerFormat]
[KnownType(typeof(SRTSRField))]
[KnownType(typeof(SRTSRValue))]
public class StartRunTestSetResponse
{
[DataMember(Name="Type"), XmlAttribute("Type")]
public string type { get; set; }
[DataMember(Name = "Fields", IsRequired = true), XmlElement("Fields")]
public List<SRTSRField> fields { get; set; }
internal StartRunTestSetResponse() { fields = new List<SRTSRField>(); }
}
[DataContract(Name = "Field", Namespace = "")]
[KnownType(typeof(SRTSRValue))]
public class SRTSRField
{
[DataMember(Name = "Name"), XmlAttribute("Name")]
public string name {get; set;}
[DataMember(Name = "Value"), XmlElement("Value")]
public SRTSRValue value { get; set; }
}
[DataContract(Name = "Value", Namespace = "")]
public class SRTSRValue
{
[DataMember, XmlText]
public string value { get; set; }
}
Now, it doesn't work; at the moment it parses down to the Fields element and then any child of it is null.
You can simplify your model
public class Entity
{
[XmlAttribute]
public string Type { get; set; }
[XmlArrayItem("Field")]
public Field[] Fields { get; set; }
}
public class Field
{
[XmlAttribute]
public string Name { get; set; }
public string Value { get; set; }
}
So deserialization would be
XmlSerializer ser = new XmlSerializer(typeof(Entity));
using (StringReader sr = new StringReader(xmlstring))
{
var entity = (Entity)ser.Deserialize(sr);
}
[XmlRoot(ElementName="Field")]
public class Field {
[XmlElement(ElementName="Value")]
public string Value { get; set; }
[XmlAttribute(AttributeName="Name")]
public string Name { get; set; }
}
[XmlRoot(ElementName="Fields")]
public class Fields {
[XmlElement(ElementName="Field")]
public List<Field> Field { get; set; }
}
[XmlRoot(ElementName="Entity")]
public class Entity {
[XmlElement(ElementName="Fields")]
public Fields Fields { get; set; }
[XmlAttribute(AttributeName="Type")]
public string Type { get; set; }
}
Createdy by: http://xmltocsharp.azurewebsites.net/
It's really useful
I would create a dictionary using xml linq.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication74
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string,int?> dict1 = doc.Descendants("Field")
.GroupBy(x => (string)x.Attribute("Name"), y => string.IsNullOrEmpty((string)y.Element("Value")) ? null : (int?)y.Element("Value"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
Related
So i've been trying to deserialize this xml file to some objects, its simple enough but it keeps returning null to the objects, the data that i need is stored inside the attributes of the element.
Here is the XML.
<exchangerates xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="Valutakurser" author="Danmarks Nationalbank" refcur="DKK" refamt="1">
<dailyrates id="2020-10-20">
<currency code="AUD" desc="Australske dollar" rate="442,98"/>
<currency code="BGN" desc="Bulgarske lev" rate="380,53"/>
</dailyrates>
And this is the deserialisation code.
public static T DeserializeElement<T>(string filename)
{
try
{
T result;
XmlSerializer serializer = new XmlSerializer(typeof(T), new
XmlRootAttribute("exchangerates"));
using (TextReader tr = new StringReader(filename))
{
result = (T)serializer.Deserialize(tr);
}
return result;
}
catch { throw; }
}
And these are the objects
[XmlRoot(Namespace = "http://www.w3.org/2001/XMLSchema-instance",
ElementName = "exchangerates",
DataType = "Valutakurser")]
[Serializable]
public class Valutakurser
{
[XmlArray("dailyrates")]
public DateTime Id { get; set; }
public Currency Currency { get; set; }
}
[Serializable]
public class Currency
{
public string Code { get; set; }
public string Desc { get; set; }
public double Rate { get; set; }
public Currency() { }
}
Currently I keep getting this error and everything returned null:
InvalidOperationException: For non-array types, you may use the following attributes: XmlAttribute, XmlText, XmlElement, or XmlAnyElement
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Valutakurser));
Valutakurser valutakurser = (Valutakurser)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "exchangerates")]
public class Valutakurser
{
[XmlAttribute]
public DateTime id { get; set; }
[XmlElement("dailyrates")]
public DailyRates DalyRates { get; set; }
}
public class DailyRates
{
[XmlElement("currency")]
public List<Currency> Currency { get; set; }
}
public class Currency
{
[XmlAttribute]
public string code { get; set; }
[XmlAttribute]
public string desc { get; set; }
[XmlAttribute]
public double rate { get; set; }
public Currency() { }
}
}
I'm attempting to deserialize an XML file into corresponding C# objects. I've read through the other answers and I'm at a loss as to what I'm doing wrong.
Here's my XML file
<?xml version="1.0" encoding="utf-8"?>
<DialogueObjectCollection>
<DialogueObjects>
<DialogueObject id="0001">
<name>CHARACTER</name>
<dialogue>
<text tag="1">Hi, this is a message.</text>
<text tag="2">Yup.</text>
<text tag="3">What do you want to do?
<options>
<option action= "1">Go back.</option>
<option action="4">Tell me something new.</option>
</options>
</text>
<text tag= "4">This is the end.</text>
</dialogue>
</DialogueObject>
<DialogueObject id="0002">
<name>CHARACTER2</name>
<dialogue>
<text tag="1">Hi.</text>
</dialogue>
</DialogueObject>
</DialogueObjects>
</DialogueObjectCollection>
Here are my classes:
{
[Serializable(), XmlRoot("DialogueObject")]
public class DialogueObject
{
[XmlAttribute("id")]
public string id { get; set; }
[XmlElement("name")]
public string name { get; set; }
[XmlAttribute("tag")]
public int tag { get; set; }
public OptionHolder option;
public DialogueHolder dialogueHolder { get; set; }
[XmlAttribute("action")]
public string action { get; set; }
}
[Serializable(), XmlRoot("dialogue")]
public class DialogueHolder
{
[XmlArray("dialogue")]
[XmlArrayItem("text", IsNullable = false)]
public TextItem[] dialogue { get; set; }
}
[Serializable(),XmlRoot("text")]
public class TextItem
{
[XmlAttribute]
public string tag { get; set; }
public string text { get; set; }
}
[Serializable(),XmlRoot("option")]
public class OptionHolder
{
[XmlAttribute]
public string action;
[XmlElement("option")]
public string option;
}
[Serializable()]
[System.Xml.Serialization.XmlRoot("DialogueObjectCollection")]
public class DialogueObjectCollection
{
[XmlArray("DialogueObjects")]
[XmlArrayItem("DialogueObject", typeof(DialogueObject))]
public DialogueObject[] dialogueObject { get; set; }
}
And my method:
public static void LoadDialogue()
{
DialogueObjectCollection dialogueCollection = null;
string path = "Content/NPCdata.xml";
XmlSerializer serializer = new XmlSerializer(typeof(DialogueObjectCollection));
Console.WriteLine("LOADDINGGGG");
StreamReader reader = new StreamReader(path);
dialogueCollection = (DialogueObjectCollection)serializer.Deserialize(reader);
//test print Console.WriteLine(dialogueCollection.dialogueObject.First().dialogueHolder.dialogue.First().text);
}
So, it's telling me that dialogueHolder is returning null. I can get the dialogueObject.First().name and id to print. I can't figure out why the dialogue text isn't loading into it. (My attempts at fixing it included adding the XmlRootNode attributes and adding more classes-- I'm new to XML serialization in C#)
Thanks for any help!
try code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
LoadDialogue(FILENAME);
}
public static void LoadDialogue(string path)
{
XmlReader reader = XmlReader.Create(path);
XmlSerializer serializer = new XmlSerializer(typeof(DialogueObjectCollection));
DialogueObjectCollection dialogueObjectCollection = (DialogueObjectCollection)serializer.Deserialize(reader);
}
}
[Serializable(), XmlRoot("DialogueObject")]
public class DialogueObject
{
[XmlAttribute("id")]
public string id { get; set; }
[XmlElement("name")]
public string name { get; set; }
[XmlAttribute("tag")]
public int tag { get; set; }
public OptionHolder option;
[XmlElement("dialogue")]
public DialogueHolder dialogueHolder { get; set; }
[XmlAttribute("action")]
public string action { get; set; }
}
[Serializable(), XmlRoot("dialogue")]
public class DialogueHolder
{
[XmlElement("text")]
public TextItem[] texItem { get; set; }
}
[Serializable(), XmlRoot("text")]
public class TextItem
{
[XmlAttribute]
public string tag { get; set; }
[XmlText()]
public string text { get; set; }
[XmlArray("options")]
[XmlArrayItem("option")]
public OptionHolder[] options { get; set; }
}
[Serializable(), XmlRoot("option")]
public class OptionHolder
{
[XmlAttribute]
public string action;
[XmlElement("option")]
public string option;
}
[XmlRoot("DialogueObjectCollection")]
public class DialogueObjectCollection
{
[XmlArray("DialogueObjects")]
[XmlArrayItem ("DialogueObject")]
public DialogueObject[] dialogueObject { get; set; }
}
}
I want to read an XML file with C# (unity project) in order to display some content. the XML file is given by a TALEND Job in Talend Studio.
I've converted an XML file to C# classes and I'm now trying to read this XML (stored in a file) to manage the content.
For the moment, I'm able to read some properties but the most interesting tag are nul. There is no error during the deserialization.
private const string filename = "/Applications/TalendStudio-7.1.1/studio/workspace/LOCAL_PROJECT/process/job1_0.1.item";
void Start()
{
// Create an instance of the XmlSerializer.
XmlSerializer serializer = new XmlSerializer(typeof(Xml2CSharp.ProcessType));
// Declare an object variable of the type to be deserialized.
Xml2CSharp.ProcessType i;
using (Stream reader = new FileStream(filename, FileMode.Open))
{
// Call the Deserialize method to restore the object's state.
i = (Xml2CSharp.ProcessType)serializer.Deserialize(reader);
Debug.Log(i);
}
}
the XML file starts with :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<talendfile:ProcessType
xmlns:talendfile="TalendFile.xsd" xmlns:TalendMapper="http://www.talend.org/mapper" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
defaultContext="Default" jobType="Standard" xmi:version="2.0">
<context confirmationNeeded="false" name="Default">
<contextParameter comment="" name="max_rows" prompt="max_rows?" promptNeeded="false" type="id_Integer" value="10"/>
</context>
<context confirmationNeeded="false" name="prod">
<contextParameter comment="" name="max_rows" prompt="max_rows?" promptNeeded="false" type="id_Integer" value="30"/>
</context>
<context confirmationNeeded="false" name="qa">
<contextParameter comment="" name="max_rows" prompt="max_rows?" promptNeeded="false" type="id_Integer" value="20"/>
</context>
<parameters>
<elementParameter field="TEXT" name="SCREEN_OFFSET_X" show="false" value="0"/>
<elementParameter field="TEXT" name="SCREEN_OFFSET_Y" show="false" value="0"/>
<elementParameter field="TEXT" name="REPOSITORY_CONNECTION_ID" show="false" value=""/>
etc...
the 'context' and 'parameter' are empty. Thank you for your help.
Use xml serialization :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(ProcessType));
ProcessType processType = (ProcessType)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "ProcessType", Namespace = "TalendFile.xsd")]
public class ProcessType
{
[XmlAttribute("defaultContext")]
public string defaultContext { get; set; }
[XmlAttribute("jobType")]
public string jobType { get; set; }
[XmlElement("context", Namespace = "")]
public List<Context> context { get; set; }
[XmlArray("parameters", Namespace = "")]
[XmlArrayItem("elementParameter", Namespace = "")]
public List<Parameters> parameters { get; set; }
}
[XmlRoot("context", Namespace = "")]
public class Context
{
[XmlAttribute("confirmationNeeded")]
public string confirmationNeeded { get; set; }
[XmlAttribute("name")]
public string name { get; set; }
[XmlElement("contextParameter", Namespace = "")]
public ContextParameter contextParameter { get; set; }
}
[XmlRoot("contextParameter", Namespace = "")]
public class ContextParameter
{
[XmlAttribute("comment")]
public string comment { get; set; }
[XmlAttribute("name")]
public string name { get; set; }
[XmlAttribute("prompt")]
public string prompt { get; set; }
[XmlAttribute("promptNeeded")]
public string promptNeeded { get; set; }
[XmlAttribute("type")]
public string type { get; set; }
[XmlAttribute("value")]
public int value { get; set; }
}
[XmlRoot("parameters", Namespace = "")]
public class Parameters
{
[XmlAttribute("field")]
public string field { get; set; }
[XmlAttribute("name")]
public string name { get; set; }
[XmlAttribute("show", Namespace = "")]
public string show { get; set; }
private int? _value { get; set; }
[XmlAttribute("value")]
public string value {
get { return _value.ToString(); }
set { _value = value == string.Empty ? (int?)null : int.Parse(value); }
}
}
}
I am looking into loading a large number of InfoPath XML files into Cosmos DB as Json files to test a possible project. But I am struggling with converting the XML files to Json and then loading back into a c# class. I think this is related to the namespace that InfoPath puts into the XML but I'm not sure. I thought at first I should try to remove all the namespace references from the XML but now I'm wondering if I just need to work more on the definition of the class file. To generate the class file I used Visual Studio "paste as Json". I assumed after loading the XML, saving to Json, then using that as the basis for the new class file, I could load right back into the object but when I call DeserializeObject it always ends up null.
Is this because the class file definition needs to be changed or should I instead look to try and clean the XML prior to converting to Json?
Sample XML
<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:myProject:-myXSD-2017-05-05T14-19-13" solutionVersion="1.0.0.2046" productVersion="16.0.0.0" PIVersion="1.0.0.0" href="https://myportal.sharepoint.com/sites/mySite/myProject/Forms/template.xsn"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.4"?>
<?mso-infoPath-file-attachment-present?>
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2017-05-05T14:19:13" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls" xmlns:ma="http://schemas.microsoft.com/office/2009/metadata/properties/metaAttributes" xmlns:d="http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields" xmlns:q="http://schemas.microsoft.com/office/infopath/2009/WSSList/queryFields" xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:dms="http://schemas.microsoft.com/office/2009/documentManagement/types" xmlns:tns="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-US">
<my:Admin>
<my:Routing_Order>
<my:Approver-1_Order>1</my:Approver-1_Order>
<my:Approver-2_Order>5</my:Approver-2_Order>
<my:Approver-3_Order>4</my:Approver-3_Order>
</my:Routing_Order>
</my:Admin>
<my:Request_Status>Save as Draft</my:Request_Status>
<my:Request_Type>CAPEX</my:Request_Type>
</my:myFields>
Class file
namespace xml_to_json
{
public class Rootobject
{
public MyMyfields mymyFields { get; set; }
}
public class MyMyfields
{
public string xmlnsmy { get; set; }
public string xmlnsxsi { get; set; }
public string xmlnsxhtml { get; set; }
public string xmlnspc { get; set; }
public string xmlnsma { get; set; }
public string xmlnsd { get; set; }
public string xmlnsq { get; set; }
public string xmlnsdfs { get; set; }
public string xmlnsdms { get; set; }
public string xmlnstns { get; set; }
public string xmlnss1 { get; set; }
public string xmlnshttp { get; set; }
public string xmlnstm { get; set; }
public string xmlnssoap { get; set; }
public string xmlnssoapenc { get; set; }
public string xmlnsmime { get; set; }
public string xmlnssoap12 { get; set; }
public string xmlnswsdl { get; set; }
public string xmlnsxd { get; set; }
public string xmllang { get; set; }
public MyAdmin myAdmin { get; set; }
public string myRequest_Status { get; set; }
public string myRequest_Type { get; set; }
}
public class MyAdmin
{
public MyRouting_Order myRouting_Order { get; set; }
}
public class MyRouting_Order
{
public string myApprover1_Order { get; set; }
public string myApprover2_Order { get; set; }
public string myApprover3_Order { get; set; }
}
}
Console test code
namespace xml_to_json
{
class Program
{
static void Main(string[] args)
{
XmlDocument myDoc = new XmlDocument();
string sourcedir = #"C:\Users\mystuff\Downloads\test-clean\";
string xmlfilein = #"test";
string xmlfile = string.Concat(sourcedir, xmlfilein, ".xml");
string jsonfileout = string.Concat(sourcedir, xmlfilein, ".json");
myDoc.Load(xmlfile);
string jsonText = JsonConvert.SerializeXmlNode(myDoc.LastChild);
File.WriteAllText(jsonfileout, jsonText);
Rootobject obj = new Rootobject();
obj = JsonConvert.DeserializeObject<Rootobject>(jsonText);
Console.WriteLine(obj.mymyFields.myRequest_Status);
}
}
}
Try code below using 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
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement routingOrder = doc.Descendants().Where(x => x.Name.LocalName == "Routing_Order").FirstOrDefault();
Dictionary<string, string> orders = routingOrder.Elements()
.GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
string status = (string)doc.Descendants().Where(x => x.Name.LocalName == "Request_Status").FirstOrDefault();
string requestType = (string)doc.Descendants().Where(x => x.Name.LocalName == "Request_Type").FirstOrDefault();
}
}
}
Using suggestion from jdweng and XDocument helped to clean the XML file for easier transition to Json. Below is a sample of code I used to clean the document.
XDocument newxdoc = XDocument.Load(xmlfile);
newxdoc.DescendantNodes().Where(e => e.NodeType.ToString().StartsWith("ProcessingInstruction")).Remove();
string newstringdoc = RemoveAllNamespaces(newxdoc.ToString());
newxdoc = XDocument.Parse(newstringdoc);
Data ("1.0.0") from attribute "version" fall into property. But the property "Event" in the same class remains empty.
If cut namespace from XML, it will work.
My XML:
<rootnode>
<ns:eventresponse xmlns:ns="somenamespace" version="1.0.0">
<event id="694717028">
<somedata>val</somedata>
</event>
</ns:eventresponse>
</rootnode>
My class:
[XmlRoot("rootnode")]
public class RootNode
{
[XmlElement(ElementName = "eventresponse", Namespace = "somenamespace")]
public EventResponseData EventResponse { get; set; }
}
public class EventResponseData
{
[XmlElement("event")]
public EventData Event { get; set; }
[XmlAttribute("version")]
public string Version { get; set; }
}
public class TvEventData
{
[XmlAttribute("id")]
public string EventID { get; set; }
[XmlElement("somedata")]
public string SomeData { get; set; }
}
My Deserializer:
using (var reader = XmlReader.Create(new StringReader(xml)))
{
reader.MoveToContent();
var obj = (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
Your event element is implicitly in the same namespace in the XML due to namespace defaulting, so you should specify that in your declaration:
public class EventResponseData
{
[XmlElement(ElementName = "event", Namespace = "somenamespace")]
public EventData Event { get; set; }
[XmlAttribute("version")]
public string Version { get; set; }
}