C# obtaining XML attributes [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C#: Read XML Attribute using XmlDocument
In C# if I were to have the XMLDocument containing:
<Hello>
<Person:"Alan" Saying:"My name is Alan">
</Hello>
Then how might I obtain the single attribute "Saying"? I've found code which works when a single attribute is contained within the "<>" however it does not appear to work where there are multiple attributes inside as is above.
Any help would be much appreciated, I'm rather a C# novice :)

First off, that is not valid xml. I think you want something like
<Hello>
<Person name="Alan" Saying="My name is Alan" />
</Hello>
and the simplest way to get Alan's Saying is
XmlDocument doc = new XmlDocument();
doc.Load("filename.xml");
string saying = doc.SelectSingleNode("//Person[#name=Alan]").Attributes["saying"].Value;
for a more detailed explanation of why that works, see XPath Examples

Your XML should be:
<Hello>
<Person name="Alan" saying="My name is Alan"/>
</Hello>
Your class to deserialize this would be:
public class Hello
{
public Person Person { get; set; }
}
public class Person
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Saying { get; set; }
}
How to use it:
// Create a new XmlSerializer instance with the type of the test class
XmlSerializer SerializerObj = new XmlSerializer(typeof(Hello));
// load xml into string reader
StringReader reader = new StringReader(yourXmlString);
// Load the object saved above by using the Deserialize function
Hello LoadedObj = (Hello)SerializerObj.Deserialize(reader);
Check out the MSDN article for more info on how to use the XmlSerializer

Related

There is an error in XML document (2, 2).What does this mean?

I am trying to read XML document.
My XML:
<?xml version="1.0" encoding="utf-8"?>
<SplashScreen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Path>SplashScreen/Image-King</Path>
</SplashScreen>
My code which is reading XML:
XmlGameScreen = new XmlManager<GameScreen>();
XmlGameScreen.Type = currentscreen.Type;
currentscreen = XmlGameScreen.Load("LoadXML/SplashScreen.xml");
And
public Type Type;
public T Load(string path)
{
T instance;
using (TextReader textreader = new StreamReader(path))
{
XmlSerializer xml = new XmlSerializer(Type);
instance = (T)xml.Deserialize(textreader);
}
return instance;
}
I am getting error on instance = (T)xml.Deserialize(textreader); Is my XML document wrong? I am trying to read <Path>.
Update :
My Internal Exception:
Cannot serialize member 'MyRPGgame.SplashScreen._image' of type 'Microsoft.Xna.Framework.Graphics.Texture2D'
In my case it appears one of the Visual Studio 2017 version 15.5 updates caused this error when trying to open SSRS projects. The solution is to delete the *.rptproj.rsuser file from the project folder and try again.
My experience from it would be that in the 2nd line in the 2nd chararacter, there is an error.
have a look if your class names are different from the XML tags. are you maybe changing the "XML Root name" to a different one.
Have a look at the XML structure and which class are you serializing to which node.
Also, read the
MSDN Documentation about the XmlRootAttribute Class.
That usually means you have whitespace at the start of the file; check for a line-break before the <?xml.... Even better: please show the first few bytes (preferably as far as <SplashScreen) of the file as viewed in a binary editor.
It could also mean you have an invisible unicode or control character somewhere before the <SplashScreen
Just wanted to share what worked for me. I had a similar error
System.InvalidOperationException: There is an error in XML document (1, 40).
---> System.InvalidOperationException: <tsResponse xmlns='http://xxxyyyzzzz.com/api'> was not expected.
I was trying to deserialize a string to an object of type tsResponse.
After adding the following attribute [Serializable, XmlRoot(ElementName = "tsResponse", Namespace = "http://xxxyyyzzzz.com/api")] to the class tsResponse i was able to resolve my issue.
[Serializable, XmlRoot(ElementName = "tsResponse", Namespace = "http://xxxyyyzzzz.com/api")]
public class tsResponse
{
[XmlElement]
public CredentialsXml credentials { get; set; }
}
I.e had to add Namespace attribute (System.Xml.Serialization).
Try this: When you are deserializing XML to List just add an extra
line to the start i.e ArrayOfAddressDirectory as follows and don't put any space at start and end of file.
<?xml version="1.0"?>
<ArrayOfAddressDirectory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AddressDirectory>
<Owner>MS. Dhoni</Owner>
<Age>48</Age>
<Company>India</Company>
</AddressDirectory>
</ArrayOfAddressDirectory>
Here is the C# code:
namespace XmlReadProgram
{
public class AddressDirectory
{
public string Owner { get; set; }
public string Age { get; set; }
public string Company { get; set; }
}
public class Program
{
static void Main(string[] args)
{
List<AddressDirectory> adlist = new List<AddressDirectory>();
using (FileStream fileStream = File.OpenRead(#"E:\inputDirectory\address.xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<AddressDirectory>));
adlist = (List<AddressDirectory>)serializer.Deserialize(fileStream);
}
//You can use foreach to print all data
Console.WriteLine(adlist[0].Owner);
Console.WriteLine(adlist[0].Age);
Console.WriteLine(adlist[0].Company);
}
}
}
In my case, a property with [XmlArrayAttribute] had the getter accessing a field with [XmlIgnoreAttribute] that was left uninitialized.
The problem in your case it's definitely the confusion between Type and template T. You are trying to construct Serializer with Type --> new XmlSerializer(Type) and then deserialize with template T ----> (T)xml.Deserialize. So the solution is to replace Type in constructing with typeof(T), and this should eliminate the initial XML document problem of (2, 2).

Deserialize XML Array Where Root is Array and Elements Dont Follow Conventions

The XML I am getting is provided by an outside source so I don't have the ability to easily reformat it. I would like to use xml attributes on my entities instead of having to write a linq query that knows how the XML and entity is formatted. Here is an example:
<?xml version="1.0"?>
<TERMS>
<TERM>
<ID>2013-2</ID>
<DESC>Spring 2013</DESC>
</TERM>
<TERM>
<ID>2013-3</ID>
<DESC>Summer 2013 Jun&Jul</DESC>
</TERM>
</TERMS>
I know the the XMLSerializer expects ArrayOfTerm instead of TERMS for example, but that I can tweak my entity to use a different element name with the xml attributes such as this:
public class TermData
{
[XmlArray("TERMS")]
[XmlArrayItem("TERM")]
public List<Term> terms;
}
public class Term
{
[XmlElement("ID")]
public string id;
[XmlElement("DESC")]
public string desc;
}
and I am deserializing the data like so:
TermData data;
XmlSerializer serializer = new XmlSerializer(typeof(TermData));
using (StringReader reader = new StringReader(xml))
{
data = (TermData)serializer.Deserialize(reader);
}
return View(data.terms);
The problem I am facing is that TERMS is the root and the array itself. If the XML were to have a root element that was not the array, I could edit my TermData class like so and it would deserialize correctly (already tested).
[XmlRoot("ROOT")]
public class TermData
{
[XmlArray("TERMS")]
[XmlArrayItem("TERM")]
public List<Term> terms;
}
Note that using TERMS as the XMLRoot does not work. Right now, my code is throwing
InvalidOperationException: There is an error in XML document (2,2).
InnerException: "<TERMS xmlns=" was not expected.
This would lead me to believe that the XML is not formatted correctly, but from my understanding the example I gave is perfectly valid XML.
This would all be trivial if I could edit the source xml, but there could be tons of other responses like this and I need to be able to flex for whatever I might get. What I'm trying to confirm is whether or not the XMLSerializer can support this type of XML structure. I've tested just about everything and can't get it deserialize without editing the XML. It would also be convenient if I didn't have to define a wrapper class (TermData) to hold the list, but this seems to only work if the xml follows the naming conventions for the serializer (ArrayOfTerm, etc).
Maybe you can try :
[XmlRoot("TERMS")]
public class TermData
{
public TermData()
{
terms = new List<Term>();
}
[XmlElement("TERM")]
public List<Term> terms{get;set;}
}
public class Term
{
[XmlElement("ID")]
public string id{get;set;}
[XmlElement("DESC")]
public string desc{get;set;}
}
Hope this will help,

XmlDeserialize conditional Deserialization based on Attribute Value

I am trying to Deserialize the following XML:
<Test><string name="Name">Test name</string><string name="Description">Some fake description.</string></Test>
Into the following class.
[XmlRoot("Test")]
public class Test
{
[XmlElement("string")]
public string Name;
[XmlElement("string")]
public string Description;
}
Using the code I am doing it with.
var xml = #"<Test><string name=""Name"">Test name</string><string name=""Description"">Some fake description.</string></Test>";
XmlReader reader = new XmlTextReader(new StringReader(xml));
XmlSerializer serializer = new XmlSerializer(typeof(Test));
serializer.Deserialize(reader);
When I run this I get an InvalidOperationException with the message
There was an error reflecting type 'Test'.
If I comment out the Description property, it works. I can get the attribute value or the text, but I can't get just the XmlText with the element is string and the "name" Attribute has a specific value.
Is this even possible without using LINQ?
As per my comment:
Certainly won't be able to do it without changing something. You're
telling .NET that Description is an element when it's an attribute of
the 'string' element. Use LINQ
Here is an example of the LINQ, it's quite straightforward to extend and decouples your XML from your class (which is often a good thing!).
var xml = #"<Test><string name=""Name"">Test name</string><string name=""Description"">Some fake description.</string></Test>";
var xdoc = XDocument.Parse(xml);
var output = from test in xdoc.Elements("Test")
let strings = test.Elements("string").ToDictionary(e => e.Attribute("name").Value, e => e.Value)
select new Test () { Name = strings["Name"],
Description = strings["Description"] };
The reason is that you are not using XmlElement as intended, the element name "string" must be unique the class. The "name" attribute is not taken into account.
So, in summary, it is not possible to deserialize that xml document automatically, you would need to implement the deserialization method by yourself.
For that you would need:
public class Foo {
[XmlAttribute("name")]
public string Name {get;set;}
[XmlText]
public string Value {get;set;}
}
Then, in the parent type:
[XmlRoot("Test")]
public class Test
{
[XmlElement("string")]
public List<Foo> Items {get;set;}
}
This it the only way you can process that shape XML unless you use IXmlSerializable (very hard).

How would I parse this XML String?

I have an XML string like this:
<Summary>Foo</Summary><Description>Bar</Description>
I want to read this into a class object:
class Foobar()
{
string Summary {get;set;}
string Description {get;set;}
}
I tried using XmlTextReader, but it throws an exception that no root element was found. This is what I tried:
using (XmlTextReader reader = new XmlTextReader(new StringReader(comment)))
{
while (reader.Read())
//do something here
}
I also tried deserializing it directly into an object like this:
[XmlTypeAttribute]
public class Foobar
{
[XmlElementAttribute("Summary")]
public string Summary { get; set; }
[XmlElementAttribute("Description")]
public string Description { get; set; }
}
This fails as well because I cannot define a [XmlRootElement] for the class Foobar, since there is no root element.
Define a root element
<root>
<Summary>Foo</Summary>
<Description>Bar</Desciption>
</root>
You need to set root element for that your xaml would be
<root>
<Summary>Foo</Summary><Description>Bar</Description>
</root>
For Rootelement in XMLSeralizatoion : http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute.aspx
The easiest way is probably to manually add a root element.
string xml = "<root>" + comment + "</root>";
Then you can parse it with whichever method you want.
Use a constructor form that allows for XMLFragments (chunks of XML that could be valid if put into a single element, but which are not so-rooted):
using (XmlTextReader reader = new XmlTextReader(comment, XmlNodeType.Element, null))
{
while (reader.Read())
//do something here
}
Better yet, use Create(), which gives more flexibility still.

XML Deserialization with C# .NET 3.5

I Have this XML File
<?xml version="1.0" standalone="yes"?>
<Root>
<Object>
<referenceName>People</referenceName>
<query>select * from people</query>
</Object>
<Object>
<referenceName>Countries</referenceName>
<query>select * from countries</query>
</Object>
</Root>
I need to convert into an object with C#.
I got confused how to do it.
Kindly note that I can have alot of objects in the xml file.
I know that i have to use an [XMLArray......
Thanks
The simplest trick here is at the VS command line:
xsd example.xml
xsd example.xsd /classes
Et voila; one example.cs file with example C# that shows how to get that xml from .NET objects via XmlSerializer.
In this case, I expect the following would work:
public class Root
{
[XmlElement("Object")]
public List<SomeOtherObject> Objects { get; set; }
}
public class SomeOtherObject
{
[XmlElement("referenceName")]
public string Name { get; set; }
[XmlElement("query")]
public string Query { get; set; }
}
update: validated it; yup, it works...
XmlSerializer ser = new XmlSerializer(typeof(Root));
using (XmlReader reader = XmlReader.Create(
new StringReader(xml)))
{
var obj = (Root)ser.Deserialize(reader);
// use obj
}
Use the xsd.exe tool to generate an initial set of classes to start with. Once you have those, tweak if needed (post the generated classes) and use System.Xml.Serialization.XmlSerializer to deserialize back into the runtime object.

Categories

Resources