De-serialising XML into list yields empty list - c#

I've been trying to de serialise an XML file into a list, but whatever I do, the list ends up with a count of 0.
I've been searching Stack like I normally do, tried all kinds of things, but am at my wit's end. What's going wrong here?
My XML:
<?xml version="1.0" encoding="utf-8"?>
<lijst>
<lijst_item>
<id>1</id>
<naam>NAME REDACTED</naam>
<archived>false</archived>
</lijst_item>
<lijst_item>
<id>2</id>
<naam>NAME REDACTED</naam>
<archived>false</archived>
</lijst_item>
<lijst_item>
<id>3</id>
<naam>NAME REDACTED</naam>
<archived>false</archived>
</lijst_item>
</lijst>
Lijst_item object:
[XmlType("Lijst_item")]
public class Lijst_item
{
[XmlAttribute("id", DataType = "int")]
public int ID { get; set; }
[XmlElement("naam")]
public string Name { get; set; }
[XmlElement("archived", DataType ="boolean")]
public bool isArchived { get; set; }
public Lijst_item()
{
}
public Lijst_item(int id, string name, bool archived)
{
this.ID = id;
this.Name = name;
this.isArchived = archived;
}
}
Code used to de serialise:
using (StreamReader sr = new StreamReader(sFile))
{
XmlSerializer deserializer = new XmlSerializer(typeof(List<Lijst_item>), new XmlRootAttribute("lijst"));
var Test = (List<Lijst_item>)deserializer.Deserialize(sr);
}
Convert xml to List by Deserialize in c#
Did not help me: Exactly what am I doing wrong? Is my XML malformed? My object? Can I for some reason not use a List?

Try this...
Usings...
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
Classes...(created using your XML at http://xmltocsharp.azurewebsites.net/)
[XmlRoot(ElementName = "lijst_item")]
public class Lijst_item
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "naam")]
public string Naam { get; set; }
[XmlElement(ElementName = "archived")]
public string Archived { get; set; }
}
[XmlRoot(ElementName = "lijst")]
public class Lijst
{
[XmlElement(ElementName = "lijst_item")]
public List<Lijst_item> Lijst_item { get; set; }
}
Code...
string strXML = #"<?xml version=""1.0"" encoding=""utf-8""?>
<lijst>
<lijst_item>
<id>1</id>
<naam>NAME REDACTED</naam>
<archived>false</archived>
</lijst_item>
<lijst_item>
<id>2</id>
<naam>NAME REDACTED</naam>
<archived>false</archived>
</lijst_item>
<lijst_item>
<id>3</id>
<naam>NAME REDACTED</naam>
<archived>false</archived>
</lijst_item>
</lijst>";
byte[] bufXML = ASCIIEncoding.UTF8.GetBytes(strXML);
MemoryStream ms1 = new MemoryStream(bufXML);
// Deserialize to object
XmlSerializer serializer = new XmlSerializer(typeof(Lijst));
try
{
using (XmlReader reader = new XmlTextReader(ms1))
{
Lijst deserializedXML = (Lijst)serializer.Deserialize(reader);
}// put a break point here and mouse-over Label1Text and Label2Text ….
}
catch (Exception ex)
{
throw;
}

Related

How to get a list of values on a XML response?

I get from a webservice a XML like this:
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<Get_PersonResponse
xmlns="http://tempuri.org/">
<Get_PersonResult
xmlns:a="http://schemas.datacontract.org/example"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:LASTNAME>DOE</a:LASTNAME>
<a:EMAIL/>
<a:FIRSTNAME>JONH</a:FIRSTNAME>
<a:NUM_CARD/>
<a:ID_PERSON>12345456</a:ID_PERSON>
<a:PHONE/>
</Get_PersonResult>
<RESP_COMMENT>"Person found"</RESP_COMMENT>
</Get_PersonResponse>
</s:Body>
</s:Envelope>
I want to check if RESP_COMMENT is empty. Then if is not empty get all the values (a:FIRSTNAME, a:LASTNAME, etc)
I got the a:FIRSTNAME on the fiddle but I am not sure if I have to do a bucle for every single value or is a better way to do it:
https://dotnetfiddle.net/cOsX6s
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(output);
XmlNodeList nodeList = xmldoc.GetElementsByTagName("a:FIRSTNAME");
string lastname = string.Empty;
foreach (XmlNode node in nodeList)
{
firstname = node.InnerText;
Console.Write(firstname);
}
Try xml serialization :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication177
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
StringReader sReader = new StringReader(xml);
XmlReader xReader = XmlReader.Create(sReader);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(xReader);
}
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
}
public class Body
{
[XmlElement(ElementName = "Get_PersonResponse", Namespace = "http://tempuri.org/")]
public Get_PersonResponse Get_PersonResponse { get; set; }
}
public class Get_PersonResponse
{
[XmlElement(Namespace = "http://tempuri.org/")]
public string RESP_COMMENT { get; set; }
[XmlElement(ElementName = "Get_PersonResult", Namespace = "http://tempuri.org/")]
public Get_PersonResult Get_PersonResult { get; set; }
}
public class Get_PersonResult
{
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string LASTNAME { get;set;}
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string EMAIL { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string FIRSTNAME { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string NUM_CARD { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string ID_PERSON { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string PHONE { get; set; }
}
}
There should be a way to get this values using xpath. I have tried a few different things and it seems that the empty prefix on namespace xmlns="http://tempuri.org/" is causing problems, see the element Get_PersonResponse namespace attribute.
<Get_PersonResponse xmlns="http://tempuri.org/">
To overcome this problem we need to remove the namespace that is causing the problem before loading the xml.
using System;
using System.Xml;
public class Program
{
public static void Main()
{
string output = #"<s:Envelope
xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
<s:Body>
<Get_PersonResponse
xmlns=""http://tempuri.org/"">
<Get_PersonResult
xmlns:a=""http://schemas.datacontract.org/example""
xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
<a:LASTNAME>DOE</a:LASTNAME>
<a:EMAIL/>
<a:FIRSTNAME>JONH</a:FIRSTNAME>
<a:NUM_CARD/>
<a:ID_PERSON>12345456</a:ID_PERSON>
<a:PHONE/>
</Get_PersonResult>
<RESP_COMMENT>""Person found!""</RESP_COMMENT>
</Get_PersonResponse>
</s:Body>
</s:Envelope>";
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(output.Replace(#"xmlns=""http://tempuri.org/""", ""));
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmldoc.NameTable);
nsmgr.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("a", "http://schemas.datacontract.org/example");
var personResultNode = xmldoc.SelectSingleNode("//s:Envelope/s:Body/Get_PersonResponse/Get_PersonResult", nsmgr);
foreach (var nodes in personResultNode.ChildNodes)
{
var personAttribute = (XmlNode)nodes;
Console.WriteLine($"{personAttribute.LocalName}: {personAttribute.InnerText}");
}
Console.Read();
}
}
BTW: I have also tried to add an empty prefix for namespace xmlns="http://tempuri.org/" to the XmlNamespaceManager but that didn't help.

C# .net 4.6 XmlSerializerNamespaces XmlSerializer output problem

I need the following output from Pojo classes to Xml.
It's .net 4.6.1, C#.
Problem is in the namespaces and the produced prefixes.
How can I get the node:
<blablubb:Message SOAP-ENV:mustUnderstand="1" xmlns:blablubb="urn:blablubb-com:schemas:blablubb">
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<blablubb:Message SOAP-ENV:mustUnderstand="1" xmlns:blablubb="urn:blablubb-com:schemas:blablubb">
<blablubb:Type>INET_TRANS</blablubb:Type>
<blablubb:Function>RECEIVE_CUSTOMER_ORDER</blablubb:Function>
<blablubb:Sender>CONNECT</blablubb:Sender>
<blablubb:Receiver>CONNECT</blablubb:Receiver>
<blablubb:SentAt>2018-08-30T10:43:37+02:00</blablubb:SentAt>
<blablubb:ExpiresAt>2018-09-30T10:43:37+02:00</blablubb:ExpiresAt>
</blablubb:Message>
</SOAP-ENV:Header>
<SOAP-ENV:Body><ORDERS xmlns="urn:blablubb-com:schemas:inbound_distribution_transactions_create_customer_order_request" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BUYER></BUYER>
<CONTACT_REFERENCE>OAK</CONTACT_REFERENCE>
<EAN_LOCATION_DELIVERY_ADDRESS>10901000</EAN_LOCATION_DELIVERY_ADDRESS>
<CURRENCY_CODE>EUR</CURRENCY_CODE>
<ORDER_DATE>2018-08-27T09:01:01</ORDER_DATE>
<OUR_CUSTOMER_NO>2</OUR_CUSTOMER_NO>
<SUPPLIER_ADDRESS_NO></SUPPLIER_ADDRESS_NO>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Pojos that get serialized:
SoapDocument:
[Serializable]
[XmlRoot("Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[XmlInclude(typeof(SoapHeader))]
public class SoapDocument {
[XmlElement("Header")]
public SoapHeader soapHeader { get; set; }
[XmlElement("Body",typeof(IfsOrdersXmlDocument))]
public object soapBody { get; set; }
}
SoapHeader :
[Serializable]
[XmlRoot("Header")]
[XmlInclude(typeof(SoapMessage))] // include type class IfsOrderLineXmlDocument
public class SoapHeader {
[XmlElement("Message", Namespace = "urn:blablubb-com:schemas:blablubb")]
public SoapMessage soapMessage { get; set; }
}
SoapBody :
[Serializable]
[XmlInclude(typeof(IfsXmlDocument)), XmlInclude(typeof(IfsOrdersXmlDocument))]
[SoapInclude(typeof(IfsXmlDocument)), SoapInclude(typeof(IfsOrdersXmlDocument))]
public class SoapBody {
[XmlElement("Body")]
public IfsXmlDocument soapBody { get; set; }
}
SoapMessage:
[Serializable]
//[XmlType("blablubb")]
[XmlRoot("Message", Namespace = "urn:blablubb-com:schemas:blablubb")]
public class SoapMessage {
[XmlElement("Type")]
public string Type { get; set; }
[XmlElement("Function")]
public string Function { get; set; }
[XmlElement("Sender")]
public string Sender { get; set; }
[XmlElement("Receiver")]
public string Receiver { get; set; }
[XmlElement("SentAt")]
public string SentAt { get; set; }
[XmlElement("ExpiresAt")]
public string ExpiresAt { get; set; }
}
Code that produces the Xml,
So the problem is in the namespaces and prefixes ......
XmlSerializerNamespaces ns = createSoapDocument();
XmlSerializer serializer = new XmlSerializer(typeof(HeinzApi.Soap.SoapDocument), new Type[] { typeof(IfsXmlDocument), typeof(IfsOrdersXmlDocument) });
FileStream fs = new FileStream(xmlTargetPath, FileMode.Create);
serializer.Serialize(fs, soapDocument, ns);
fs.Close();`
And this is what I get:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<Message xmlns="urn:blablubb-com:schemas:blablubb">
<Type>INET_TRANS</Type>
<Function>RECEIVE_CUSTOMER_ORDER</Function>
<Sender>CONNECT</Sender>
<Receiver>CONNECT</Receiver>
<SentAt>2018-01-03T10:43:37+02:00</SentAt>
<ExpiresAt>2018-08-02T10:43:37+02:00</ExpiresAt>
</Message>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
This is the createSoapDocument method that adds namespaces to the XmlSerializer Namespaces object:
private XmlSerializerNamespaces createSoapDocument() {
soapMessage.Type = "INET_TRANS";
soapMessage.Function = "RECEIVE_CUSTOMER_ORDER";
soapMessage.Sender = "CONNECT";
soapMessage.Receiver = "CONNECT";
soapMessage.SentAt = "2018-01-03T10:43:37+02:00";
soapMessage.ExpiresAt = "2018-08-02T10:43:37+02:00";
soapHeader.soapMessage = soapMessage;
soapDocument.soapHeader = soapHeader;
//soapDocument.soapBody = (IfsXmlDocument)targetXmlBaseDocument; ;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
ns.Add("blablubb", "urn:blablubb-com:schemas:blablubb");
return ns;
}
Edit: This is the result after adding the namespaces to XmlSerializerNamespaces:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:blablubb="urn:blablubb-com:schemas:blablubb" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<blablubb:Message>
<blablubb:Type>INET_TRANS</blablubb:Type>
<blablubb:Function>RECEIVE_CUSTOMER_ORDER</blablubb:Function>
<blablubb:Sender>CONNECT</blablubb:Sender>
<blablubb:Receiver>CONNECT</blablubb:Receiver>
<blablubb:SentAt>2018-01-03T10:43:37+02:00</blablubb:SentAt>
<blablubb:ExpiresAt>2018-08-02T10:43:37+02:00</blablubb:ExpiresAt>
</blablubb:Message>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
You need to tell the serializer about your blahblubb namespace by adding it to your XmlSerializerNamespaces object.
ns.Add("blablubb", "urn:bla-com:schemas:blablubb");
Don't forget to change
[XmlElement("Body")]
to
[XmlElement("Body", Namespace="urn:bla-com:schemas:blablubb")]

There is an error in XML document C# Xamarin

I am getting the following error in my Xamarin Forms app but I don't know what the problem is:
System.InvalidOperationException: There is an error in XML document.
items xmlns=''> was not expected
I have a basic XML file that I have added as an embedded resource:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<name>a name</name>
<address>an address</address>
<postcode>a postcode</postcode>
</item>
<item>
<id>2</id>
<name>name 2</name>
<address>address 2</address>
<postcode>postcode 2</postcode>
</item>
<item>
<id>3</id>
<name>name 3</name>
<address>address 3</address>
<postcode>postcode 3</postcode>
</item>
</items>
I have the following method to read the XML file:
public static List<Item> GetItemList()
{
var assembly = typeof(MyNewPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("MyNewApp.allitems.xml");
List<Item> itemsFullList;
using (var reader = new System.IO.StreamReader(stream))
{
var serializer = new XmlSerializer(typeof(List<Item>));
itemsFullList = (List<Item>)serializer.Deserialize(reader);
}
return itemsFullList;
}
I also have a standard class to represent each item:
public class Item
{
public Item()
{
}
public string name { get; set; }
public string address { get; set; }
public string postcode { get; set; }
}
I don't know why I am getting the error as from what I can see, the XML document is formatted just fine. I am using this article as a guide but I am having no luck: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/files/
Anyone know what I am doing wrong here?
Thanks.
That class structure will not deserialize to a list of Item, it will deserialize to a single object that has a property of type Item[].
You will probably want to change class and property names to make more sense, but this is how Visual Studio generates the class structure based on your xml (Edit > Paste Special)
void Main()
{
string xml = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<items>
<item>
<id>1</id>
<name>a name</name>
<address>an address</address>
<postcode>a postcode</postcode>
</item>
<item>
<id>2</id>
<name>name 2</name>
<address>address 2</address>
<postcode>postcode 2</postcode>
</item>
<item>
<id>3</id>
<name>name 3</name>
<address>address 3</address>
<postcode>postcode 3</postcode>
</item>
</items>";
using (MemoryStream ms = new MemoryStream())
{
XDocument.Parse(xml).Save(ms);
ms.Position = 0;
using (var reader = new System.IO.StreamReader(ms))
{
var serializer = new XmlSerializer(typeof(items));
var itemsFullList = (items)serializer.Deserialize(reader);
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(ElementName = "items", Namespace = "", IsNullable = false)]
public partial class items
{
private itemsItem[] itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("item")]
public itemsItem[] item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class itemsItem
{
private byte idField;
private string nameField;
private string addressField;
private string postcodeField;
/// <remarks/>
public byte id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public string address
{
get
{
return this.addressField;
}
set
{
this.addressField = value;
}
}
/// <remarks/>
public string postcode
{
get
{
return this.postcodeField;
}
set
{
this.postcodeField = value;
}
}
}

Deserializing XML Into class with different members C#

I am facing a problem in deserializing xml into a class object. The class has a slightly different structure than the xml, so am unable to deserialize it. Following is the main code
public class Customer
{
[XmlElement(ElementName = "CustomerName")]
public string Name { get; set; }
}
public class XmlCheck
{
[XmlElement(ElementName = "Customer")]
public Customer Customer { get; set; }
public List<Customer> CustomersList { get; set; }
}
class Program
{
static string xml = #"<?xml version=""1.0"" ?>
<XmlCheck>
<Customer>
<CustomerName>Omer</CustomerName>
</Customer>
<Customer>
<CustomerName>Ali</CustomerName>
</Customer>
</XmlCheck>";
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(XmlCheck), new XmlRootAttribute("XmlCheck"));
using (var stringReader = new StringReader(xml))
using (var reader = XmlReader.Create(stringReader))
{
var xmlResult = (XmlCheck)serializer.Deserialize(reader);
xmlResult.CustomersList.Add(xmlResult.Customer);
Console.WriteLine(xmlResult.Customer.Name);
}
}
Is there any way, to deserialize the xml into the customers list without having to insert that node inside the xml? Currently this only deserializes the first customer node that has name as 'Omer' and it adds that to the list.
I know how to accomplish the above by writing a custom xml reader, but need to use xml deserialization for this. However, if this isn't possible using xml deserialization, any way to achieve this using any customer (s/de)erializer?
Please try this:
public class Customer
{
[XmlElement(ElementName = "CustomerName")]
public string Name { get; set; }
}
[XmlRoot("XmlCheck")]
public class XmlCheck
{
[XmlElement(ElementName = "Customer")]
public List<Customer> CustomersList { get; set; }
}
class Program
{
static string xml = #"<?xml version=""1.0"" ?>
<XmlCheck>
<Customer>
<CustomerName>Omer</CustomerName>
</Customer>
<Customer>
<CustomerName>Ali</CustomerName>
</Customer>
</XmlCheck>";
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(XmlCheck), new XmlRootAttribute("XmlCheck"));
using (var stringReader = new StringReader(xml))
using (var reader = XmlReader.Create(stringReader))
{
var xmlResult = (XmlCheck)serializer.Deserialize(reader);
//xmlResult.CustomersList.Add(xmlResult.Customer);
foreach(var c in xmlResult.CustomersList)
{
Console.WriteLine(c.Name);
}
}
}
}
I got it from: Is it possible to deserialize XML into List<T>?

C# XmlSerializer generates wrong XML string

I use the following code to serialize my class as XML string:
AXMLItem rc = new AXMLItem();
rc.Attributes.Add(new Reports.ReportConfiguration.Questionnaire.FormObjectXMLItem.Attribute { Value = "ddddd" });
MemoryStream fw = new MemoryStream();
var serializer = new XmlSerializer(typeof(AXMLItem ));
using (StringWriter textWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter))
{
serializer.Serialize(xmlWriter, rc);
}
string myString = textWriter.ToString(); //This is the output as a string
}
that class definition
[XmlType(TypeName = "A")]
public class AXMLItem
{
[XmlType(TypeName = "B")]
public List<Attr> Attrs { get; set; }
[XmlType(TypeName = "C")]
public class Attr
{
[XmlText]
public string Value { get; set; }
}
public AXMLItem()
{
Attrs = new List<Attr>();
}
}
which gives me the following string
<?xml version="1.0" encoding="utf-16"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<B>
<C>ddddd</C>
</B>
</A>
but I need
<?xml version="1.0" encoding="utf-16"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<C>ddddd</C>
</A>
Keep in ming that there can be many <C>...</C> items. How to fix it ?
just add an XmlElement attribute to the collection property:
[XmlElement("C")]
public List<Attr> Attrs { get; set; }

Categories

Resources