I have gone through all the answers as at this date (2020-07-24), and there has to be a simpler more familiar way to solve this problem, which is the following.
Two scenarios... One is if the XML string is well-formed, i.e. it begins with something like <?xml version="1.0" encoding="utf-16"?>
or its likes, before encountering the root element, which is <msg>
in the question. The other is if it is NOT well-formed, i.e. just the root element (e.g. <msg>
in the question) and its child nodes only.
Firstly, just a simple class that contains the properties that match, in case-insensitive names, the child nodes of the root node in the XML. So, from the question, it would be something like...
public class TheModel
{
public int Id { get; set; }
public string Action { get; set; }
}
The following is the rest of the code...
// These are the key using statements to add.
using Newtonsoft.Json;
using System.Xml;
bool isWellFormed = false;
string xml = = @"
<msg>
<id>1</id>
<action>stop</action>
</msg>
";
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
if (isWellFormed)
{
xmlDocument.RemoveChild(xmlDocument.FirstChild);
/* i.e. removing the first node, which is the declaration part.
Also, if there are other unwanted parts in the XML,
write another similar code to locate the nodes
and remove them to only leave the desired root node
(and its child nodes).*/
}
var serializedXmlNode = JsonConvert.SerializeXmlNode(
xmlDocument,
Newtonsoft.Json.Formatting.Indented,
true
);
var theDesiredObject = JsonConvert.DeserializeObject<TheModel>(serializedXmlNode);