I'm attempting to deserialize an XML response from an API. The data is as follows (I have only included a small chunk for the sake of a small post):
<ns1:alerts xmlns:ns1="http://gov.fema.ipaws.services/feed">
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
<identifier>All-Channels-Test-Message-RT_Automation_124_789f95e3-e02f-4e61-8121
My code to deserialize this data is as follows:
var serializer = new XmlSerializer(
typeof(List<Alert>),
new XmlRootAttribute("alerts") { Namespace = "http://gov.fema.ipaws.services/feed" });
var alerts = serializer.Deserialize(stream) as Alert[];
In my Alert class, I have attributes set with the namespace and root element for the alert:
[XmlRoot("alert", Namespace = "urn:oasis:names:tc:emergency:cap:1.2")]
public class Alert
When I go to deserialize a list of alert instances, I get a result of 0 instance. I have verified that the response is formatted correctly. There are 1-2 depending on the dummy alerts on the API feed. My guess is I am deserializing incorrectly. How can I deserialize this properly?
Approach 1: With Root class
You should have a Root class and contains Alerts property with applying the [XmlElement("alert", Namespace = "urn:oasis:names:tc:emergency:cap:1.2")] attribute to obtain all <alert> elements.
[XmlRoot("alerts", Namespace = "http://gov.fema.ipaws.services/feed")]
public class Root
{
[XmlElement("alert", Namespace = "urn:oasis:names:tc:emergency:cap:1.2")]
public List<Alert> Alerts { get;set; }
}
[XmlRoot("alert", Namespace = "urn:oasis:names:tc:emergency:cap:1.2")]
public class Alert
{
[XmlElement(ElementName = "identifier")]
public string Identifier { get; set; }
}
In the caller, you need to deserialize the stream as Root.
var serializer = new XmlSerializer(
typeof(Root),
new XmlRootAttribute("alerts") { Namespace = "http://gov.fema.ipaws.services/feed" });
var root = serializer.Deserialize(stream) as Root;
var alerts = root.Alerts;
Demo @ .NET Fiddle
Approach 2: With XPath
You can work with XPath as well without the need of the Root class, although the implementation is slightly complex.
// Load steam to XmlDocument
var xDocument = new XmlDocument();
xDocument.Load(stream);
// Initialize namespaces and tags
var nsm = new XmlNamespaceManager(xDocument.NameTable);
nsm.AddNamespace("ns1", "http://gov.fema.ipaws.services/feed");
nsm.AddNamespace("a", "urn:oasis:names:tc:emergency:cap:1.2");
// Search XML nodes
var alertXmlNodeList = xDocument.DocumentElement.SelectNodes("/ns1:alerts/a:alert", nsm);
// Iterate XmlNode in XMLNodeList and deserialize to Alert
List<Alert> alerts = new List<Alert>();
foreach (XmlNode alertXmlNode in alertXmlNodeList)
{
XmlSerializer serializer = new XmlSerializer(typeof(Alert));
Alert alert = serializer.Deserialize(new XmlNodeReader(alertXmlNode)) as Alert;
alerts.Add(alert);
// Or your implementation for managing `alert` directly
}
Demo @ .NET Fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With