This question already has answers here:
How does one parse XML files? [closed]
(12 answers)
Closed 7 years ago.
I'm trying to read a given file saved in xml, but I'm getting the error "Object reference not set to an instance of an object."
Edit: I cannot use any kind of serialization for this.
Easiest approach you can have for such case is using XmlSerializer. That is not the only approach you can do with .net, as there are XmlReader, XmlTextReader and XDocument to help you with that but XmlSerializer allow you to easily convert data structure to xml and back. Here is an example:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace TestXmlSerializer
{
class Program
{
static void Main(string[] args)
{
var g = new Group
{
Name="g2",
Keys = new[] {
new Key { Username="a" },
new Key { Password="b" }
}
};
Group g2;
var xs = new XmlSerializer(typeof(Group));
var s = string.Empty;
using (var tw = new StringWriter()) {
using (var xw = XmlWriter.Create(tw))
xs.Serialize(xw, g);
s = tw.ToString();
}
Console.WriteLine(s);
using (var ms = new StringReader(s))
{
using (var xw = XmlReader.Create(ms))
g2 = xs.Deserialize(xw) as Group;
}
Console.WriteLine(g2.Name);
}
}
[Serializable]
public class Key
{
[XmlAttribute]
public string Title;
[XmlAttribute]
public string Username;
[XmlAttribute]
public string Password;
[XmlAttribute]
public string Url;
[XmlAttribute]
public string Notes;
}
[Serializable]
public class Group
{
[XmlAttribute]
public string Name;
[XmlElement]
public Key[] Keys;
}
}
Related
I am using C# and have a question in relation to de serializing an XML string.
Here is my code to de serialize:
public object XmlDeserializeFromString(string objectData, Type type)
{
var serializer = new XmlSerializer(type);
object result;
using (TextReader reader = new StringReader(objectData))
{
result = serializer.Deserialize(reader);
}
return result;
}
The following XML works with the above function:
<House>
<address>21 My House</address>
<id>1</id>
<owner>Optimation</owner>
</House>
However, the XML from my Web API application does not:
<House xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MVCwithWebAPIApplication.Models">
<address>21 My House</address>
<id>1</id>
<owner>Optimation</owner>
</House>
How can I get the XmlDeserializeFromString function to work with the XML from my Web API application?
The xml return from web api has a default namespace inside. To deserialize this xml into a memory object (defined by a c# class), XmlSerialize has to know whether the class belongs to that namespace or not. This is specified by the property 'Namespace' in RootAttribute attached to that class. If the namespace in xml matches to the declared namespace in c# class, then the xml is successfully deserialized. Otherwise deserialization fails.
More information about xml namespace please see http://www.w3schools.com/xml/xml_namespaces.asp
below is the demo solution for your reference.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
namespace ConsoleApplication8 {
class Program {
static void Main(string[] args) {
var s1 = "<House><address>21 My House</address><id>1</id><owner>Optimation</owner></House>";
var s2 = "<House xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/MVCwithWebAPIApplication.Models\"><address>21 My House</address><id>1</id><owner>Optimation</owner></House>";
House house = (House)XmlDeserializeFromString(s2, typeof(House));
Console.WriteLine(house.ToString());
Console.Read();
}
public static Object XmlDeserializeFromString(string objectData, Type type) {
var serializer = new XmlSerializer(type);
object result;
using (TextReader reader = new StringReader(objectData)) {
result = serializer.Deserialize(reader);
}
return result;
}
}
//this is the only change
[XmlRoot(Namespace="http://schemas.datacontract.org/2004/07/MVCwithWebAPIApplication.Models")]
public class House {
public String address { get; set; }
public String id { get; set; }
public String owner { get; set; }
public override string ToString() {
return String.Format("address: {0} id: {1} owner: {2}", address, id, owner);
}
}
}
I have XML that is being returned back from a rest service WCF. The following is an example of the XML
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
<catalog version="1.1"><dataset id="354" name="Mariano - Ship Drift" description="Global Currents, Static" datatype="currents" rank="5" saropsrank="4" format="netcdf" starttime="1980-01-01T00:00:00" endtime="2019-01-01T00:00:00" extentleft="-180.0000" extentbottom="-90.0000" extentright="180.0000" extenttop="90.0000" source="STATIC" wmslayeridstr="MARIANO_currents" confidence="L" directionfrom="no" image="ne_ndbc.jpg" />
</catalog>
</string>
I need to get the value from id, name, description, etc... and put it into a list or a listbox.
WebResponse response = restWebRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
Reponse stream is the stream that holds the XML.
Any ideas?
XDocument doc = XDocument.Load(responseStream);
var elem = doc.Descendants().FirstOrDefault(el => el.Name.LocalName == "dataset");
if(elem != null)
{
var attID = elem.Attribute("id");
if(attID != null)
Console.WriteLine(attID.Value);
}
OR
You could directly get the IEnumerable with an anonymous type:
XDocument doc = XDocument.Parse(xml);
var values = doc.Descendants("dataset")
.Select(el => new { id = el.Attribute("id").Value,
name = el.Attribute("name").Value
}
);
Here's another approach: (I tested your XML by loading it from a file.)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
namespace delete4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Load();
}
void Load()
{
var stream = new FileStream("c:\\pj\\data.txt", FileMode.Open);
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "string";
xRoot.IsNullable = true;
xRoot.Namespace = "http://schemas.microsoft.com/2003/10/Serialization/";
XmlSerializer s = new XmlSerializer(typeof(sstring), xRoot);
var o = s.Deserialize(stream) as sstring; // o is your loaded object
stream.Close();
}
[ XmlRoot("string"), XmlType("string")]
public class sstring
{
public Catalog catalog;
}
public class Catalog
{
public Dataset dataset;
}
public class Dataset
{
[XmlAttribute("name")]
public string Name;
[XmlAttribute("id")]
public string ID;
[XmlAttribute("description")]
public string Description;
}
}
}
Does anyone know how to convert a Hashtable to an XML String then back to a HashTable without using the .NET based XMLSerializer. The XMLSerializer poses some security concerns when code runs inside of IE and the browser's protected mode is turned on -
So basically I am looking for an easy way to convert that Hashtable to string and back to a Hashtable.
Any sample code would be greatly appreciated.
Thanks
You could use the DataContractSerializer class:
using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
public class MyClass
{
public string Foo { get; set; }
public string Bar { get; set; }
}
class Program
{
static void Main()
{
var table = new Hashtable
{
{ "obj1", new MyClass { Foo = "foo", Bar = "bar" } },
{ "obj2", new MyClass { Foo = "baz" } },
};
var sb = new StringBuilder();
var serializer = new DataContractSerializer(typeof(Hashtable), new[] { typeof(MyClass) });
using (var writer = new StringWriter(sb))
using (var xmlWriter = XmlWriter.Create(writer))
{
serializer.WriteObject(xmlWriter, table);
}
Console.WriteLine(sb);
using (var reader = new StringReader(sb.ToString()))
using (var xmlReader = XmlReader.Create(reader))
{
table = (Hashtable)serializer.ReadObject(xmlReader);
}
}
}
I don't have time to test this, but try:
XDocument doc = new XDocument("HashTable",
from de in hashTable
select new XElement("Item",
new XAttribute("key", de.Key),
new XAttribute("value", de.Value)));
All, I am trying to serialize and de-serialize a class and the de-serialization is failing. There are tons of similar threads, but I am unable to resolve this. I am getting the following error "There is an error in XML document (2, 2)" Inner expection "{" was not expected."}"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
namespace XMLSerialization
{
[System.Xml.Serialization.XmlRootAttribute(Namespace = "",
IsNullable = false)]
public class Level
{
private String _name;
private String _background;
public Level()
{
_name = "LEVEL_NAME";
_background = "LEVEL_BACKGROUND_IMAGE";
}
[XmlAttribute("LevelName")]
public String LevelName
{
get { return _name; }
set { _name = value; }
}
[XmlAttribute("Background")]
public String Background
{
get { return _background; }
set { _background = value; }
}
}
}
This is the code I use for de-serialization. The serialization is happening fine but the de-serialization is not going through. I think that I am doing a trivial mistake but I am unable to solve this!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
namespace XMLSerialization
{
class Program
{
static void Main(string[] args)
{
Level oLevel1 = new Level();
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(Level));
TextWriter textWriter = new StreamWriter("Level1.xml");
serializer.Serialize(textWriter, oLevel1, ns);
textWriter.Close();
Level oLevel2 = new Level();
XmlSerializer deserializer = new XmlSerializer(typeof(List<Level>));
TextReader textReader = new StreamReader("Level1.xml");
oLevel2 = (Level)deserializer.Deserialize(textReader);
textReader.Close();
}
}
}
I think you need to change the line
XmlSerializer deserializer = new XmlSerializer(typeof(List<Level>));
To
XmlSerializer deserializer = new XmlSerializer(typeof(Level));
You a serializing a Level and are trying to deserizalize a List<Level>.
If I create a class in C#, how can I serialize/deserialize it to a file? Is this somethat that can be done using built in functionality or is it custom code?
XmlSerializer; note that the exact xml names can be controlled through various attributes, but all you really need is:
a public type
with a default constructor
and public read/write members (ideally properties)
Example:
using System;
using System.Xml;
using System.Xml.Serialization;
public class Person {
public string Name { get; set; }
}
static class Program {
static void Main() {
Person person = new Person { Name = "Fred"};
XmlSerializer ser = new XmlSerializer(typeof(Person));
// write
using (XmlWriter xw = XmlWriter.Create("file.xml")) {
ser.Serialize(xw, person);
}
// read
using (XmlReader xr = XmlReader.Create("file.xml")) {
Person clone = (Person) ser.Deserialize(xr);
Console.WriteLine(clone.Name);
}
}
}
You need to use class XmlSerializer. Main methods are Serialize and Deserialize. They accept streams, text readers\writers and other classes.
Code sample:
public class Program
{
public class MyClass
{
public string Name { get; set; }
}
static void Main(string[] args)
{
var myObj = new MyClass { Name = "My name" };
var fileName = "data.xml";
var serializer = new XmlSerializer(typeof(MyClass));
using (var output = new XmlTextWriter(fileName, Encoding.UTF8))
serializer.Serialize(output, myObj);
using (var input = new StreamReader(fileName))
{
var deserialized = (MyClass)serializer.Deserialize(input);
Console.WriteLine(deserialized.Name);
}
Console.WriteLine("Press ENTER to finish");
Console.ReadLine();
}
}