I have an XML and I load it in an class.
This is my XML
<out_policySystem xmlns:msl="http://www.ibm.com/xmlmap" xmlns:io="" xmlns:xs4xs="http://www.w3.org/2001/XMLSchema">
<BGBAResultadoOperacion>
<Severidad>OK</Severidad>
</BGBAResultadoOperacion>
<permiteOperar>true</permiteOperar>
<Lista xmlns:ns0=\"http://CalypsoPolicySystem_lib/service\">
<Codigo>ODM-006</Codigo>
<Descripcion>Aviso</Descripcion>
<DescripcionTecnica>XXXX</DescripcionTecnica>
</Lista>
</out_policySystem>
I have define my classes like this.
[XmlRoot(ElementName = "out_policySystem")]
public partial class output_policySystem
{
public BGBAResultadoOperacion BGBAResultadoOperacion { get; set; }
public bool permiteOperar { get; set; }
public List[] Lista { get; set; }
}
public partial class BGBAResultadoOperacion
{
public string Severidad { get; set; }
}
public partial class List
{
public string Codigo { get; set; }
public string Descripcion { get; set; }
public string DescripcionTecnica { get; set; }
}
I read this like this.
XmlNodeList elemlist = xDoc.GetElementsByTagName("out_policySystem");
string result = elemlist[0].InnerXml;
XmlSerializer serializer = new XmlSerializer(typeof(BGBAResultadoOperacion));
using (StringReader reader = new StringReader(result))
{
result = (BGBAResultadoOperacion)(serializer.Deserialize(reader));
}
the value of result is this.
<BGBAResultadoOperacion><Severidad>OK</Severidad></BGBAResultadoOperacion><permiteOperar>true</permiteOperar><Lista><Codigo>ODM-006</Codigo><Descripcion>Aviso</Descripcion><DescripcionTecnica>xxxx</DescripcionTecnica></Lista>
What I need is to get the value of BGBAResultadoOperacion
when i set
using (StringReader reader = new StringReader(result))
{
result = (BGBAResultadoOperacion)(serializer.Deserialize(reader));
}
result get XML error...
There are multiple root elements. Line 1, position 76.
XML node out_policySystem has three root elements inside it. I need to parse only BGBAResultadoOperacion
How can I get it?
Thanks
That's because of this line:
elemlist[0].InnerXml
Which returns an XML Fragment, not an XML Document.
<BGBAResultadoOperacion>
<Severidad>OK</Severidad>
</BGBAResultadoOperacion>
<permiteOperar>true</permiteOperar>
<Lista xmlns:ns0=\"http://CalypsoPolicySystem_lib/service\">
<Codigo>ODM-006</Codigo>
<Descripcion>Aviso</Descripcion>
<DescripcionTecnica>XXXX</DescripcionTecnica>
</Lista>
So either use the .OuterXML, or use XElement.CreateReader() as described in the answer here: Serialize an object to XElement and Deserialize it in memory
Related
I have the following XML;
<?xml version="1.0" encoding="UTF-8" ?>
<feedback>
<report_metadata>
<org_name>example.com</org_name>
</report_metadata>
</feedback>
and the following Feedback.cs class;
[XmlRoot("feedback", Namespace = "", IsNullable = false)]
public class Feedback
{
[XmlElement("report_metadata")]
public MetaData MetaData { get; set; }
}
[XmlType("report_metadata")]
public class MetaData
{
[XmlAttribute("org_name")]
public string Organisation { get; set; }
}
When I attempt to deserialize, the value for Organisation is null.
var xml = System.IO.File.ReadAllText("example.xml");
var serializer = new XmlSerializer(typeof(Feedback));
using (var reader = new StringReader(input))
{
var feedback = (Feedback)serializer.Deserialize(reader);
}
Yet, when I change Feedback.cs to the following, it works (obviously the property name has changed).
[XmlType("report_metadata")]
public class MetaData
{
//[XmlAttribute("org_name")]
public string org_name { get; set; }
}
I want the property to be Organisation, not org_name.
In the example XML file org_name is an XML element, not an XML attribute. Changing
[XmlAttribute("org_name")] to [XmlElement("org_name")] at the Organisation property will deserialize it as an element:
[XmlElement("org_name")]
public string Organisation { get; set; }
probably just typo
[XmlAttribute("org_name")]
public string Organisation { get; set; }
was supposed to be
[XmlElement("org_name")]
public string Organisation { get; set; }
Try to modify your Xml classes like
[XmlRoot(ElementName = "report_metadata")]
public class MetaData
{
[XmlElement(ElementName = "org_name")]
public string Organisation { get; set; }
}
[XmlRoot(ElementName = "feedback")]
public class Feedback
{
[XmlElement(ElementName = "report_metadata")]
public MetaData MetaData { get; set; }
}
Then you will get your desired output like
class Program
{
static void Main(string[] args)
{
Feedback feedback = new Feedback();
var xml = System.IO.File.ReadAllText(#"C:\Users\Nullplex6\source\repos\ConsoleApp4\ConsoleApp4\Files\XMLFile1.xml");
var serializer = new XmlSerializer(typeof(Feedback));
using (var reader = new StringReader(xml))
{
feedback = (Feedback)serializer.Deserialize(reader);
}
Console.WriteLine($"Organization: {feedback.MetaData.Organisation}");
Console.ReadLine();
}
}
Output:
I have BIObject class
public class BIObject
{
public string Database { get; set; }
public string Schema { get; set; }
public string Name { get; set; }
public string ObjectType { get; set; }
}
and also have below XML
<root>
<objects>
<object database="LynxReporting" schema="dbo" name="rptusp_GLTDRSummary" type="P"/>
<object database="IntraDay" schema="dbo" name="BMHGLCloseDetails" type="T"/>
<object database="LynxReporting" schema="dbo" name="factGeneralLedger" type="P"/>
</objects>
</root>
I need to create List<IBObject> from the XML
Note: I load the XML from database into a property of type SqlXml so I need to convert SqlXml to List<IBObject>
Looked at couple of answers but could not figure out how I can do that.
EDIT:
I used below code
using (StringReader reader = new StringReader(myXmlString))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<BIObject>));
List<BIObject> objs = (List<BIObject>)serializer.Deserialize(reader);
}
but got error
There is an error in XML document (1, 2).
and
root xmlns='' was not expected.
Create a class which "represent" your xml structure
[XmlRoot("root")]
public class BIObjects
{
public BIObjects()
{
Objects = new List<BIObject>();
}
[XmlArray("objects")]
[XmlArrayItem("object")]
public List<BIObject> Objects { get; set; }
}
public class BIObject
{
[XmlAttribute("database")]
public string Database { get; set; }
[XmlAttribute("schema")]
public string Schema { get; set; }
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("type")]
public string ObjectType { get; set; }
}
Then use same serializer code you provide in the question
using (StringReader reader = new StringReader(myXmlString))
{
XmlSerializer serializer = new XmlSerializer(typeof(BIObjects));
var objs = (BIObjects)serializer.Deserialize(reader);
// use results
// foreach(BIObject obj in objs.Objects)
}
I know there are several posts out there with this topic, but I can't seem to figure out what is the problem here. I have serialized and deserialized xml several times, and never had this error.
The exception message is:
There is an error in XML document (1, 2).
With InnerException:
<InvoiceChangeRequest xmlns=''> was not expected.
XML file I want to deserialize:
<ns1:InvoiceChangeRequest xmlns:ns1="http://kmd.dk/fie/external_invoiceDistribution">
<CONTROL_FIELDS>
<STRUCTURID>0000000001</STRUCTURID>
<OPERA>GET</OPERA>
<WIID>000050371220</WIID>
</CONTROL_FIELDS>
<HEADER_IN>
<MANDT>751</MANDT>
<BELNR>1234567890</BELNR>
</HEADER_IN>
<ITEMS>
<ITEM_FIELDS_IN>
<BUZEI>001</BUZEI>
<BUKRS>0020</BUKRS>
</ITEM_FIELDS_IN>
</ITEMS>
</ns1:InvoiceChangeRequest>
Class I'm trying to deserialize to:
[XmlRoot(Namespace = "http://kmd.dk/fie/external_invoiceDistribution", IsNullable = false)]
public class InvoiceChangeRequest
{
[XmlElement("CONTROL_FIELDS")] public ControlFields Styrefelter;
[XmlElement("HEADER_IN")] public HeaderIn HeaderfelterInd;
[XmlElement("ITEMS")] public Items Linjer;
}
public class HeaderIn
{
[XmlElement("MANDT")] public string Kommunenummer;
[XmlElement("BELNR")] public string RegnskabsbilagsNummer;
}
public class Items
{
[XmlElement("ITEM_FIELDS_IN")] public Itemfield[] ItemfelterInd;
}
public class Itemfield
{
[XmlElement("BUZEI")] public string Linjenummer;
[XmlElement("BUKRS")] public string Firmakode;
}
Deserialization code:
XmlSerializer serializer = new XmlSerializer(typeof(InvoiceChangeRequest));
var request = serializer.Deserialize(new StringReader(output)) as InvoiceChangeRequest;
In your XML file your root element is the namespace http://kmd.dk/fie/external_invoiceDistribution with prefix ns1.
The element <CONTROL_FIELDS> isn't because it isn't prefixed. Your serialization class doesn't take this into account though. That means that it expects that <CONTROL_FIELDS> and the other elements are ALSO in the ns1 namespace.
To get the serializer parse the elements correctly add the Namespace to the elements, setting it to an empty string:
[XmlRoot(Namespace = "http://kmd.dk/fie/external_invoiceDistribution", IsNullable = false)]
public class InvoiceChangeRequest
{
[XmlElement("CONTROL_FIELDS", Namespace = "")]
public ControlFields Styrefelter { get; set; }
[XmlElement("HEADER_IN", Namespace = "")]
public HeaderIn HeaderfelterInd { get; set; }
[XmlElement("ITEMS", Namespace = "")]
public Items Linjer { get; set; }
}
This will de-serialize the given XML as intended.
In case of de-serialization issues I often create the classes in memory and then serialize that so I can inspect the resulting XML. That often gives clues on what is missing or being added compared to the input document:
var ms = new MemoryStream();
serializer.Serialize(ms, new InvoiceChangeRequest {
Styrefelter = new ControlFields { Opera="test"}
});
var s = Encoding.UTF8.GetString(ms.ToArray());
And then inspect s for differences.
You can replace 'ns1:' with string.Empty.
Below classes should serialize.
public class Item
{
[XmlElement("BUZEI")]
public string Buzei { get; set; }
[XmlElement("BUKRS")]
public string Bukrs { get; set; }
}
public class Header
{
[XmlElement("MANDT")]
public string Mandt { get; set; }
[XmlElement("BELNR")]
public string Belnr { get; set; }
}
public class ControlFields
{
[XmlElement("STRUCTURID")]
public string StructuredId { get; set; }
[XmlElement("OPERA")]
public string Opera { get; set; }
[XmlElement("WIID")]
public string Wild { get; set; }
}
public class InvoiceChangeRequest
{
[XmlElement("CONTROL_FIELDS")]
public ControlFields ControlFields { get; set; }
[XmlElement("HEADER_IN")]
public Header Header { get; set; }
[XmlArray("ITEMS")]
[XmlArrayItem("ITEM_FIELDS_IN")]
public List<Item> Items { get; set; }
}
I am trying to deserialize and read a simple XML file, the following code finishes without error, but the deserialization was not performed.
My message has one node, three elements below that. After the Deserialize call, I am trying to read one of the properties and it is empty.
public class Program
{
private string response = #"<?xml version=""1.0""?>
<ApplicationException xmlns = ""http://schemas.datacontract.org/2004/07/System"" xmlns:x=""http://www.w3.org/2001/XMLSchema"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
<Name xmlns = """" i:type=""x:string"">System.ApplicationException</Name>
<Message xmlns = """" i:type=""x:string"">Error Message 12345</Message>
<DataPoints xmlns = """" i:nil=""true""/>
</ApplicationException>";
private XElement xElement;
private ExceptionClass theException;
public TestXML()
{
xElement = XElement.Parse(response);
var xmlSerializer = new XmlSerializer(typeof(ExceptionClass));
using (var reader = xElement.CreateReader())
{
theException = (ExceptionClass)xmlSerializer.Deserialize(reader);
}
Console.WriteLine(theException.Message); // nothing is showing up
}
}
[XmlRoot(Namespace = "http://schemas.datacontract.org/2004/07/System",
ElementName = "ApplicationException")]
public class ExceptionClass
{
public String Name { get; set; }
public String Message { get; set; }
public String DataPoints { get; set; }
}
The problem is you are setting the XML namespaces of the elements to null whereas the root element has a namespace. Try this:
public class ExceptionClass
{
[XmlElement(Namespace="")]
public String Name { get; set; }
[XmlElement(Namespace = "")]
public String Message { get; set; }
[XmlElement(Namespace = "")]
public String DataPoints { get; set; }
}
That should work...
I have a Yaml file:
https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml
And a class:
public class IconSearch
{
public string Name { get; set; }
public string ClassName { get; set; }
public IEnumerable<string> Filters { get; set; }
}
Can you tell me how I can deserialize the yaml to an IEnumerable of objects?
I expect something like this to work, but it returns null - I'm guessing it's because one of my properties is not the root node (icons). Instead, I'm trying to serialize the children of the root?
var input = new StringReader(reply);
var yaml = new YamlStream();
yaml.Load(input);
var icons = deserializer.Deserialize<IconSearch>(input);
The class you are trying to deserialize to seems to be missing properties.
I went the round about way of converting yaml to json to csharp and this is class that was generated:
public class Rootobject
{
public Icon[] icons { get; set; }
}
public class Icon
{
public string[] categories { get; set; }
public object created { get; set; }
public string[] filter { get; set; }
public string id { get; set; }
public string name { get; set; }
public string unicode { get; set; }
public string[] aliases { get; set; }
public string[] label { get; set; }
public string[] code { get; set; }
public string url { get; set; }
}
Resources used :
YAML to JSON online
JSON to CSHARP (I used Paste special in visual studio)
Use this to deserialize
var icons = deserializer.Deserialize<RootObject>(input);
Update
I have commented out the line that you use to create YamlStream as it is not required (it positions the reader to the end of the stream instead of the beginning, which would explain why you were getting null earlier). Your main method looks as follows and works. I have also fixed the bug that Antoine mentioned
public static void Main()
{
string filePath = "https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml";
WebClient client = new WebClient();
string reply = client.DownloadString(filePath);
var input = new StringReader(reply);
//var yamlStream = new YamlStream();
//yamlStream.Load(input);
Deserializer deserializer = new Deserializer();
//var icons = deserializer.Deserialize<IconSearch>(input);
//Testing my own implementation
//if (icons == null)
// Console.WriteLine("Icons is null");
//Testing Shekhar's suggestion
var root = deserializer.Deserialize<Rootobject>(input);
if (root == null)
Console.WriteLine("Root is null");
}