How can I desearlize the below CatalogProduct tags into my CatalogProduct object using C#?
<?xml version="1.0" encoding="UTF-8"?>
<CatalogProducts>
<CatalogProduct Name="MyName1" Version="1.1.0"/>
<CatalogProduct Name="MyName2" Version="1.1.0"/>
</CatalogProducts>
Note i don't have a CatalogProducts object so want to skip that element when pulling back the into to deserialize
Thanks
var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<CatalogProducts>" +
"<CatalogProduct Name=\"MyName1\" Version=\"1.1.0\"/>" +
"<CatalogProduct Name=\"MyName2\" Version=\"1.1.0\"/>" +
"</CatalogProducts>";
var document = XDocument.Parse(xml);
IEnumerable<CatalogProduct> catalogProducts =
from c in productsXml.Descendants("CatalogProduct")
select new CatalogProduct
{
Name = c.Attribute("Name").Value,
Version = c.Attribute("Version").Value
};
Just for your information, here's an example how to really serialize and deserialize an object:
private CatalogProduct Load()
{
var serializer = new XmlSerializer(typeof(CatalogProduct));
using (var xmlReader = new XmlTextReader("CatalogProduct.xml"))
{
if (serializer.CanDeserialize(xmlReader))
{
return serializer.Deserialize(xmlReader) as CatalogProduct;
}
}
}
private void Save(CatalogProduct cp)
{
using (var fileStream = new FileStream("CatalogProduct.xml", FileMode.Create))
{
var serializer = new XmlSerializer(typeof(CatalogProduct));
serializer.Serialize(fileStream, cp);
}
}
The canonical method would be to use the xsd.exe tool twice. First, to create a schema from your example XML as so:
xsd.exe file.xml will generate file.xsd.
Then:
xsd.exe /c file.xsd will generate file.cs.
File.cs will be the object(s) you can deserialize your XML from using any one of the techniques that you can easily find here, e.g. this.
Assuming your CatalogProduct object looks something like this:
public class CatalogProduct {
public string Name;
public string Version;
}
I think Linq to Xml will be the simplest and fastest way for you
var cps1 = new[] { new CatalogProduct { Name = "Name 1", Version = "Version 1" },
new CatalogProduct { Name = "Name 2", Version = "Version 2" } };
var xml = new XElement("CatalogProducts",
from c in cps1
select new XElement("CatalogProduct",
new XAttribute("Name", c.Name),
new XAttribute("Version", c.Version)));
// Use the following to deserialize you objects
var cps2 = xml.Elements("CatalogProduct").Select(x =>
new CatalogProduct {
Name = (string)x.Attribute("Name"),
Version = (string)x.Attribute("Version") }).ToArray();
Please note that .NET offers true object graph serialization which I have not shown
Without "CatalogProduct" object i think it's very difficult, maybe with the dynamic type of .net 4.0 it's possible, but i'm not sure.
The only way i know, is to utilize the XmlSerializer class with Deserialize method, but you need the object CatalogProduct.
I hope the following link is useful:
Link
Related
I have a class file like below :
public class property : root
{
public string languages { get; set; }
}
I am trying to generate xml like below :
Final Output:
<root>
<property>
--other properties
<languages>
<en>This is English Languages description</en>
<fr></fr>
</languages>
</property>
</root>
This is how I am trying to generate the <languages> tag :
private string GenerateLanguageTag(IList<Languages> languages)
{
string lang = string.Empty;
foreach (var item in languages)
{
lang += "<" + item.IsoLanguageCode + ">" + item.Description + "</" + item.IsoLanguageCode + ">";
}
return lang;
}
output:
<root>
<property>
--other properties
<languages><en>This is English Languages description
</en><fr></fr></languages>
</property>
</root>
Code:
root root = GetData(data);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(root));
using (StringWriter xmlWriter = new StringWriter())
{
xmlSerializer.Serialize(xmlWriter, root);
value = xmlWriter.ToString();
value = value.Replace(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
value = value.Replace(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"", "");
value = value.Replace("utf-16", "ISO-8859-1");
if (File.Exists(filePath))
{
var document = XDocument.Parse(value);
document.Save(filePath);
}
}
Update:
Tags "en", "fr" and many other languages inside <languages></languages> are generated dynamically based on the languages we have in the database.
Rather than declaring languages as a string, declare it as an XElement and mark it with [XmlAnyElement("languages")]. This informs the serializer that the children of the languages property should be inserted as children of their parent <property> element. Thus your data model should look like:
public class root
{
public property property { get; set; }
}
public class property
{
[XmlAnyElement("languages")]
public XElement languages { get; set; }
}
And you would construct your model as follows:
// Your dynamic list of languages & values
var languages = new List<(string IsoLanguageCode, string Description)>
{
("en", "This is English Languages description"),
("fr", ""),
};
var root = new root()
{
property = new()
{
languages = new XElement("languages", languages.Select(l => new XElement(l.IsoLanguageCode, l.Description))),
},
};
Notes:
The documentation for XmlAnyElementAttribute indicates it should be applied to properties of type XmlElement or XmlNode (or arrays of the same), but in fact it works for properties of type XElement as well. Since LINQ-to-XML is easier to work with than the old XmlDocument API, I suggest using it instead.
In your question you show property as a subclass of root. In order to get the nesting you require, it should be a separate class contained by root, not a subclass of root.
To eliminate the xsi and xsd namespaces (without needing to do a string replacement) see XmlSerializer: remove unnecessary xsi and xsd namespaces.
Demo fiddle here.
Using Xml Linq :
string header = "<root></root>";
XDocument doc = XDocument.Parse(header);
XElement root = doc.Root;
root.Add( new XElement("property", new object[] {
new XElement("languages", new object[] {
new XElement("en", "This is English Languages description"),
new XElement("fr")
})
}));
}
I have the following (simplified) notepad file, which from what I understand is XML text:
<?xml version="1.0" encoding="utf-8"?>
<appSettings>
<add key="Active_01" value="1">
</add>
</appSettings>
I am trying to parse it using C#.
So far I have the following:
public class RFIDScanner
{
public void GetScannerConfigFile()
{
string File = ConfigurationManager.AppSettings["RFIDScannerConfiguration"];
XmlDocument doc = new XmlDocument();
doc.Load(File);
XmlNode node = doc.DocumentElement.SelectSingleNode("/appSettings");
String nodename = node.Name;
}
}
So far I know this is all correct, as:
nodename = appSettings
Which is as it should be.
My problem is, how do I retrieve the value "1" from the field "Active_01".
I now know that the node "add" is a child of the node "appSettings", and a trying to work out how to get the value stored in it.
Not sure if you wish to parse the '1' from the key Active_01, or get the 1 from the value. In Any case, you can use the following code:
public void GetScannerConfigFile()
{
string File = ConfigurationManager.AppSettings["RFIDScannerConfiguration"];
XmlDocument doc = new XmlDocument();
doc.Load(File);
var yourFile = doc.DocumentElement;
if (yourFile == null) return;
// Here you'll get the attribute key: key = Active_01 - which can be simply parsed for getting only the "1"
string key = yourFile.ChildNodes[0].Attributes["key"].Value;
// Here you'll get the number "1" from the value attribute.
string value = yourFile.ChildNodes[0].Attributes["value"].Value;
}
There are many ways, one is to use the XPath using the function you use above:
var value = doc.DocumentElement.SelectSingleNode("/appSettings/add/#value");
Another option is to use xml serialization:
You'd define classes as follows:
public class add
{
[XmlAttribute]
public string key;
[XmlAttribute]
public int value;
}
public class appSettings
{
public add add;
}
And then deserialize as follows:
var ser = new XmlSerializer(typeof(appSettings));
var xmlReader = new XmlTextReader(new StringReader(s));
appSettings settings = (appSettings) ser.Deserialize(xmlReader);
xmlReader.Close();
You can then get the values from settings
I have used this way in my code to add values to xml
may be it will help
var surveyTypeList = new XElement("SurveyTypes");
foreach (var item in modelData.SurveyTypeList)
{
if (item.IsSelected)
{
var surveyType = new XElement("SurveyType");
var id = new XElement("Id");
id.Add(item.Value);
// **var i= id.Value**
surveyType.Add(id);
surveyTypeList.Add(surveyType);
}
}
you can get value by var i= id.Value in your code;
Good day guys, How can i convert an object model to an xmldocument. this is my object:
var profile = new ProfileModel()
{
xh="aa",
FirstName = "wolverine",
LastName = "wolverine2",
PhoneNumber = "66332214477",
Email = "wolverine#wolverine.com",
SourceSystem = "TY",
ID = "ty1002224"
};
right now I'm doing it manually like this:
XDocument doc = new XDocument(new XElement("aa",
new XElement("FirstName","wolverine2"),
new XElement("LastName", "wolverine"),
new XElement("PhoneNumber", "66332214477"),
new XElement("Email", "wolverine#wolverine.com"),
new XElement("SourceSystem", "TY"),
new XElement("ID", "ty1002224")
));
but i want something more generic so i could use it to all of my object. Also, I have a case that I have a list of ProfileModel and need to convert it to xmldocument.
EDIT:
I want the output to be plain xdocument:
<aa>
<FirstName>wolverine2</FirstName>
<LastName>wolverine</LastName>
<PhoneNumber>66332214477</PhoneNumber>
<Email>wolverine#wolverine.com</Email>
<SourceSystem>TY</SourceSystem>
<ID>ty1002224</ID>
</aa>
Have a look at the XmlSerializer class
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
By using the amazing XDocument class. This will use reflection and serialize all the properties.
// in System.Xml.Linq
XDocument doc = new XDocument();
using (var writer = doc.CreateWriter())
{
// write xml into the writer
var serializer = new DataContractSerializer(objToSerialize.GetType());
serializer.WriteObject(writer, objectToSerialize);
}
Console.WriteLine(doc.ToString());
Source: How do I serialize an object into an XDocument?
I got an XML input string and want to deserialize it to an object which partially retain the raw XML.
<SetProfile>
<sessionId>A81D83BC-09A0-4E32-B440-0000033D7AAD</sessionId>
<profileDataXml>
<ArrayOfProfileItem>
<ProfileItem>
<Name>Pulse</Name>
<Value>80</Value>
</ProfileItem>
<ProfileItem>
<Name>BloodPresure</Name>
<Value>120</Value>
</ProfileItem>
</ArrayOfProfileItem>
</profileDataXml>
</SetProfile>
The class definition:
public class SetProfile
{
public Guid sessionId;
public string profileDataXml;
}
I hope the deserialization syntax looks like
string inputXML = "..."; // the above XML
XmlSerializer xs = new XmlSerializer(typeof(SetProfile));
using (TextReader reader = new StringReader(inputXML))
{
SetProfile obj = (SetProfile)xs.Deserialize(reader);
// use obj ....
}
but XMLSerializer will throw an exception and won't output < profileDataXml >'s descendants to "profileDataXml" field in raw XML string.
Is there any way to implement the deserialization like that?
If you want to deserialize that as XML, then use an XML type (either XElement or XmlElement should work) - see code below.
public class StackOverflow_11234676
{
const string XML = #"<SetProfile>
<sessionId>A81D83BC-09A0-4E32-B440-0000033D7AAD</sessionId>
<profileDataXml>
<ArrayOfProfileItem>
<ProfileItem>
<Name>Pulse</Name>
<Value>80</Value>
</ProfileItem>
<ProfileItem>
<Name>BloodPresure</Name>
<Value>120</Value>
</ProfileItem>
</ArrayOfProfileItem>
</profileDataXml>
</SetProfile>";
public class SetProfile
{
public Guid sessionId;
public XElement profileDataXml;
}
public static void Test()
{
string inputXML = XML;
XmlSerializer xs = new XmlSerializer(typeof(SetProfile));
using (TextReader reader = new StringReader(inputXML))
{
SetProfile obj = (SetProfile)xs.Deserialize(reader);
Console.WriteLine(obj.profileDataXml);
}
}
}
I would say that you can deserialize this XML.
Take a look at this article:
Attributes That Control XML Serialization
Easiest way to get it working is to use REVERSE approach. Create classes and apply xml serialization attributes and experiment with serialization until you get the same xml result as posted. Once you get the same xml, your deserialization will work.
I would use Xml.Linq for this.
setProfile obj = new setProfile();
var doc = XDocument.Parse(yourXml);
obj.sessionID = doc.Root.Element("sessionID").value;
obj.profileDataXml = doc.Root.Element("profileDataXml").value;
I'm using
List<EFacebook> facebooks = BFacebook.ReadFacebookFriends(user.EProviders
.Where(i => i.ProviderType == EProvider.EnumProviderType.Facebook)
.First().Token);
StringBuilder xml = new StringBuilder();
foreach (EFacebook i in facebooks)
{
xml.AppendFormat("<id>{0}</id>", i.id);
}
Can anybody suggest a better code to serialize each i.id into an XML string?
Edit:
The facebook object has close to 20 properties. If I XmlSerializer all 20 properties are serialized into the XML. I just need the id column.
You might want to take a look at XML Serialization already built into the .NET Framework.
You can use code similar to the following to serialize the object:
MySerializableClass myObject = new MySerializableClass();
// Insert code to set properties and fields of the object.
XmlSerializer mySerializer = new
XmlSerializer(typeof(MySerializableClass));
// To write to a file, create a StreamWriter object.
StreamWriter myWriter = new StreamWriter("myFileName.xml");
mySerializer.Serialize(myWriter, myObject);
myWriter.Close();
See: How to serialize
You can flag properties to be ignored using the XmlIgnore attribute as shown below:
public class Group
{
// The XmlSerializer ignores this field.
[XmlIgnore]
public string Comment;
// The XmlSerializer serializes this field.
public string GroupName;
}
See XMLIgnore
XmlSerializer xs = new XmlSerializer(typeof(int[]));
xs.Serialize(stream,facebooks.Select(x=>x.id).ToArray())
I would use Linq To Xml to create the Xml Tree structure
See for an example: Linq To Xml
If you're just saving the id values into an xml string then I wouldn't say that you're 'serializing' the objects.
Whenever working with XML it's much nicer to use an XML library than to wrangle with text. One obvious reason is that it guarantees your XML will be well-formed.
I'd do something like this:
List<EFacebook> facebooks = GetFriends();
var facebookIds = facebooks.Select(f => new XElement("id", f.id));
var facebookXml = new XElement("facebookIds", facebookIds);
Which will give you XML like
<facebookIds>
<id>1</id>
<id>2</id>
</facebookIds>