Reputation: 857
I am trying to deserialize this xml where all the node has the same name with a unique identifier as an attribute.
<configuration>
<setting name="host">
<value>127.0.0.1</value>
</setting>
<setting name="port">
<value>80</value>
</setting>
</configuration>
The result I am trying to achieve is:
public class Configuration
{
string host { get; set; }
int port { get; set; }
}
I read the previous question and I am still stumbling with the fact they have the same tag name.
Thank you!
Upvotes: 1
Views: 373
Reputation: 12351
You can call this "old school" but it works.
Copy the XML (or fragment, etc) and leverage Visual Studio (2015(?) and up - shot below is 2017 ) feature "Paste XML/JSON As Classes"
This helps tremendously with valid XML - particularly with the "proper" attributes that decorate the generated classes. Additionally, it's just a class, so you can customize it as you deem fit (while retaining the attributes).
For more complex XML - such as namespaces/prefixes, you'll really appreciate this. If you don't have this tool, you can use XSD.exe
(even more old school) - does the same thing for XML documents.
Auto-generated Classes from above step:
...stumbling with the fact they have the same tag name...
Don't be. XML elements can repeat - often do (e.g. sitemap.xml
of every web site out there). The generated class will help you grok it. It's a standard collection/array/list.
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class configuration
{
private configurationSetting[] settingField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("setting")]
public configurationSetting[] setting
{
get
{
return this.settingField;
}
set
{
this.settingField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class configurationSetting
{
private string valueField;
private string nameField;
/// <remarks/>
public string value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
}
Given the above, you can do this:
string rawXml = "<configuration><setting name=\"host\"><value>127.0.0.1</value></setting><setting name=\"port\"><value>80</value></setting></configuration>";
var ser = new XmlSerializer(typeof(configuration));
configuration config;
using (TextReader rdr = new StringReader(rawXml))
{
config = (configuration)ser.Deserialize(rdr);
}
foreach (configurationSetting setting in config.setting)
{
Console.WriteLine($"{setting.name} = {setting.value}");
}
Output:
host = 127.0.0.1
port = 80
Hth..
Upvotes: 2
Reputation: 2046
Try this:
XmlDocument doc = new XmlDocument();
doc.LoadXml("yourxmlhere");
Configuration configuration = new Configuration();
XmlNode root = doc.FirstChild;
if (root.HasChildNodes)
{
foreach (XmlNode item in root.ChildNodes)
{
configuration = SetValueByPropertyName(configuration, item.Attributes["name"].Value, item.FirstChild.InnerText);
}
}
The helper method to set values:
public static TInput SetValueByPropertyName<TInput>(TInput obj, string name, string value)
{
PropertyInfo prop = obj.GetType().GetProperty(name);
if (null != prop && prop.CanWrite)
{
if (prop.PropertyType != typeof(String))
{
prop.SetValue(obj, Convert.ChangeType(value, prop.PropertyType), null);
}
else
{
prop.SetValue(obj, value, null);
}
}
return obj;
}
Upvotes: 1
Reputation: 648
Load your xml as a doc
XmlDocument doc = new XmlDocument();
doc.LoadXml(your_xml_data);
Then iterate through the child nodes
Configuration configuration = new Configuration();
XmlNode root = doc.FirstChild;
//fill the configuration from the child nodes.
if (root.HasChildNodes)
{
if(root.ChildNodes[0].Name == "host")
{
configuration.host = root.ChildNodes[0].InnerText;
}
if(root.ChildNodes[1].Name == "port")
{
configuration.port = root.ChildNodes[1].InnerText;
}
}
Upvotes: 1