C# Xml select node contains node contains innertext contains text - c#

I need some help.
I have XML:
<root
xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<URLBase>someip</URLBase>
<device>
<deviceType>
urn:schemas-upnp-org:device:InternetGatewayDevice:1
</deviceType>
<friendlyName>my_router</friendlyName>
<manufacturer>Beeline</manufacturer>
<manufacturerURL>my_providers_url</manufacturerURL>
<modelDescription>Home Internet Center</modelDescription>
<modelName>my_router</modelName>
<modelNumber>Smart Box v1</modelNumber>
<modelURL>my_providers_url</modelURL>
<serialNumber>SF14F8F56358</serialNumber>
<UDN>uuid:fc4ec57e-28b1-11db-88f8-a16830956233</UDN>
<UPC>my_router</UPC>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>
<serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>
<controlURL>/upnp/control/L3Forwarding1</controlURL>
<eventSubURL>/upnp/event/L3Forwarding1</eventSubURL>
<SCPDURL>/l3frwd.xml</SCPDURL>
</service>
</serviceList>
<deviceList>
<device>
<deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>
<friendlyName>WANDevice</friendlyName>
<manufacturer>Beeline</manufacturer>
<manufacturerURL>my_providers_url</manufacturerURL>
<modelDescription>Home Internet Center</modelDescription>
<modelName>my_router</modelName>
<modelNumber>1</modelNumber>
<modelURL>my_providers_url</modelURL>
<serialNumber>SF14F8F56358</serialNumber>
<UDN>uuid:fc4ec57e-2753-11db-88f8-0060085db3f6</UDN>
<UPC>my_router</UPC>
<serviceList>
<service>
<serviceType>
urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
</serviceType>
<serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
<controlURL>/upnp/control/WANCommonIFC1</controlURL>
<eventSubURL>/upnp/event/WANCommonIFC1</eventSubURL>
<SCPDURL>/cmnicfg.xml</SCPDURL>
</service>
</serviceList>
<deviceList>
<device>
<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
<friendlyName>WANConnectionDevice</friendlyName>
<manufacturer>Beeline</manufacturer>
<manufacturerURL>my_providers_url</manufacturerURL>
<modelDescription>Home Internet Center</modelDescription>
<modelName>my_router</modelName>
<modelNumber>1</modelNumber>
<modelURL>my_providers_url</modelURL>
<serialNumber>SF14F8F56358</serialNumber>
<UDN>uuid:fc4ec57e-092a-11db-88f8-0578ab52457c</UDN>
<UPC>my_router</UPC>
<serviceList>
<service>
<serviceType>
urn:schemas-upnp-org:service:WANEthernetLinkConfig:1
</serviceType>
<serviceId>urn:upnp-org:serviceId:WANEthLinkC1</serviceId>
<controlURL>/upnp/control/WANEthLinkC1</controlURL>
<eventSubURL>/upnp/event/WANEthLinkC1</eventSubURL>
<SCPDURL>/wanelcfg.xml</SCPDURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
<serviceId>urn:upnp-org:serviceId:WANPPPConn1</serviceId>
<controlURL>/upnp/control/WANPPPConn1</controlURL>
<eventSubURL>/upnp/event/WANPPPConn1</eventSubURL>
<SCPDURL>/pppcfg.xml</SCPDURL>
</service>
</serviceList>
</device>
</deviceList>
</device>
<device>
<deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType>
<friendlyName>LANDevice</friendlyName>
<manufacturer>Beeline</manufacturer>
<manufacturerURL>my_providers_url</manufacturerURL>
<modelDescription>Home Internet Center</modelDescription>
<modelName>my_router</modelName>
<modelNumber>1</modelNumber>
<modelURL>my_providers_url</modelURL>
<serialNumber>SF14F8F56358</serialNumber>
<UDN>uuid:fc4ec57e-ba12-11db-88f8-a72469cbac1a</UDN>
<UPC>my_router</UPC>
<serviceList>
<service>
<serviceType>
urn:schemas-upnp-org:service:LANHostConfigManagement:1
</serviceType>
<serviceId>urn:upnp-org:serviceId:LANHostCfg1</serviceId>
<controlURL>/upnp/control/LANHostCfg1</controlURL>
<eventSubURL>/upnp/event/LANHostCfg1</eventSubURL>
<SCPDURL>/lanhostc.xml</SCPDURL>
</service>
</serviceList>
</device>
</deviceList>
<presentationURL>someip</presentationURL>
</device>
</root>
I need to find this node:
<service>
<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
<serviceId>urn:upnp-org:serviceId:WANPPPConn1</serviceId>
<controlURL>/upnp/control/WANPPPConn1</controlURL>
<eventSubURL>/upnp/event/WANPPPConn1</eventSubURL>
<SCPDURL>/pppcfg.xml</SCPDURL>
</service>
By this tag and innertext in it:
<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
But this can also look like that:
<serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType>
After finding this node I want to get innertext from this node:
<controlURL>/upnp/control/WANPPPConn1</controlURL>
How can I do this all?

Try something like this... To use, save your XML to a file and copy the code. It will Deserialize the whole XML to an object then you can manage it easier....
Usings...
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
Classes....
[XmlRoot(ElementName = "specVersion", Namespace = "urn:schemas-upnp-org:device-1-0")]
public class SpecVersion
{
[XmlElement(ElementName = "major", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string Major { get; set; }
[XmlElement(ElementName = "minor", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string Minor { get; set; }
}
[XmlRoot(ElementName = "service", Namespace = "urn:schemas-upnp-org:device-1-0")]
public class Service
{
[XmlElement(ElementName = "serviceType", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ServiceType { get; set; }
[XmlElement(ElementName = "serviceId", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ServiceId { get; set; }
[XmlElement(ElementName = "controlURL", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ControlURL { get; set; }
[XmlElement(ElementName = "eventSubURL", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string EventSubURL { get; set; }
[XmlElement(ElementName = "SCPDURL", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string SCPDURL { get; set; }
}
[XmlRoot(ElementName = "serviceList", Namespace = "urn:schemas-upnp-org:device-1-0")]
public class ServiceList
{
[XmlElement(ElementName = "service", Namespace = "urn:schemas-upnp-org:device-1-0")]
public List<Service> Service { get; set; }
}
[XmlRoot(ElementName = "device", Namespace = "urn:schemas-upnp-org:device-1-0")]
public class Device
{
[XmlElement(ElementName = "deviceType", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string DeviceType { get; set; }
[XmlElement(ElementName = "friendlyName", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string FriendlyName { get; set; }
[XmlElement(ElementName = "manufacturer", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string Manufacturer { get; set; }
[XmlElement(ElementName = "manufacturerURL", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ManufacturerURL { get; set; }
[XmlElement(ElementName = "modelDescription", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ModelDescription { get; set; }
[XmlElement(ElementName = "modelName", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ModelName { get; set; }
[XmlElement(ElementName = "modelNumber", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ModelNumber { get; set; }
[XmlElement(ElementName = "modelURL", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string ModelURL { get; set; }
[XmlElement(ElementName = "serialNumber", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string SerialNumber { get; set; }
[XmlElement(ElementName = "UDN", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string UDN { get; set; }
[XmlElement(ElementName = "UPC", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string UPC { get; set; }
[XmlElement(ElementName = "serviceList", Namespace = "urn:schemas-upnp-org:device-1-0")]
public ServiceList ServiceList { get; set; }
[XmlElement(ElementName = "deviceList", Namespace = "urn:schemas-upnp-org:device-1-0")]
public DeviceList DeviceList { get; set; }
}
[XmlRoot(ElementName = "deviceList", Namespace = "urn:schemas-upnp-org:device-1-0")]
public class DeviceList
{
[XmlElement(ElementName = "device", Namespace = "urn:schemas-upnp-org:device-1-0")]
public Device Device { get; set; }
}
[XmlRoot(ElementName = "root", Namespace = "urn:schemas-upnp-org:device-1-0")]
public class Root
{
[XmlElement(ElementName = "specVersion", Namespace = "urn:schemas-upnp-org:device-1-0")]
public SpecVersion SpecVersion { get; set; }
[XmlElement(ElementName = "URLBase", Namespace = "urn:schemas-upnp-org:device-1-0")]
public string URLBase { get; set; }
[XmlElement(ElementName = "device", Namespace = "urn:schemas-upnp-org:device-1-0")]
public Device Device { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
Code...
static void Main(string[] args)
{
Root dezerializedXML = new Root();
// Deserialize to object
XmlSerializer serializer = new XmlSerializer(typeof(Root));
using (FileStream stream = File.OpenRead(#"xml.xml"))
{
dezerializedXML = (Root)serializer.Deserialize(stream);
} // Put a break-point here, then mouse-over dezerializedXML
// the next line will get both of the services at that level in your XML you can probably do something with that
var v = (dezerializedXML.Device.DeviceList.Device.DeviceList.Device.ServiceList.Service);
}
OK is not the shortest answer, but hope it helps....

Select Nodes Using XPath Navigation is what you needed.
and XPath Example

Related

Define and Deserialize empty classes

I'm getting XML Data which contains an "envelope". For brevity, I'm focused on "Custom Fields" which is a collection of "Field".
Here is the part of the class definitions giving me a problem:
namespace Model.DocuSignEnvelope
{
[XmlRoot(ElementName = "CustomFields", Namespace = "http://www.docusign.net/API/3.0")]
public class CustomFields
{
[XmlElement(ElementName = "CustomField", Namespace = "http://www.docusign.net/API/3.0")]
public List<CustomField> CustomField { get; set; }
}
[XmlRoot(ElementName = "CustomField", Namespace = "http://www.docusign.net/API/3.0")]
public class CustomField
{
[XmlElement(ElementName = "Name", Namespace = "http://www.docusign.net/API/3.0")]
public string Name { get; set; } = "";
[XmlElement(ElementName = "Show", Namespace = "http://www.docusign.net/API/3.0")]
public string Show { get; set; } = "";
[XmlElement(ElementName = "Required", Namespace = "http://www.docusign.net/API/3.0")]
public string Required { get; set; } = "";
[XmlElement(ElementName = "Value", Namespace = "http://www.docusign.net/API/3.0")]
public string Value { get; set; } = "";
[XmlElement(ElementName = "CustomFieldType", Namespace = "http://www.docusign.net/API/3.0")]
public string CustomFieldType { get; set; } = "";
}
}
public static class DocuSignExtensionMethods
{
public static T DeserializeXmlX<T>(this string input) where T : class
{
XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));
using StringReader sr = new StringReader(input);
return (T)ser.Deserialize(sr);
}
}
if I get an empty list, happy times, it deserializes without issue:
<?xml version="1.0" encoding="utf-8"?>
<DocuSignEnvelopeInformation
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<RecipientStatuses>
<RecipientStatus>
<Type>Signer</Type>
...
<CustomFields />
...
but if I get a list of "empty" Custom Field
<?xml version="1.0" encoding="utf-8"?>
<DocuSignEnvelopeInformation
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<RecipientStatuses>
<RecipientStatus>
<Type>Signer</Type>
...
<CustomFields>
<CustomField />
<CustomField />
<CustomField />
</CustomFields>
...
It errors out with the Exception:
- ex {"There is an error in XML document (20, 7)."} System.Exception {System.InvalidOperationException}
- InnerException {"ReadElementContentAs() methods cannot be called on an element that has child elements. Line 20, position 7."} System.Exception {System.Xml.XmlException}
How can I tell the Deserializer to deserialize those fields as either an empty List (no valid entries) or a list with 3 empty CustomFields.
The following code works :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(EnvelopeInfo));
EnvelopeInfo fields = (EnvelopeInfo)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "EnvelopeInfo", Namespace = "http://www.docusign.net/API/3.0")]
public class EnvelopeInfo
{
[XmlElement(ElementName = "EnvelopeStatus", Namespace = "http://www.docusign.net/API/3.0")]
public EnvelopeStatus EnvelopeStatus { get; set; }
}
public class EnvelopeStatus
{
[XmlArray(ElementName = "RecipientStatuses", Namespace = "http://www.docusign.net/API/3.0")]
[XmlArrayItem(ElementName = "RecipientStatus", Namespace = "http://www.docusign.net/API/3.0")]
public RecipientStatus[] RecipientStatus { get; set; }
}
public class RecipientStatus
{
[XmlElement(ElementName = "CustomFields", Namespace = "http://www.docusign.net/API/3.0")]
public CustomFields CustomFields { get; set; }
}
public class CustomFields
{
[XmlElement(ElementName = "CustomField", Namespace = "http://www.docusign.net/API/3.0")]
public List<CustomField> CustomField { get; set; }
}
[XmlRoot(ElementName = "CustomField", Namespace = "http://www.docusign.net/API/3.0")]
public class CustomField
{
[XmlElement(ElementName = "Name", Namespace = "http://www.docusign.net/API/3.0")]
public string Name { get; set; }
[XmlElement(ElementName = "Show", Namespace = "http://www.docusign.net/API/3.0")]
public string Show { get; set; }
[XmlElement(ElementName = "Required", Namespace = "http://www.docusign.net/API/3.0")]
public string Required { get; set; }
[XmlElement(ElementName = "Value", Namespace = "http://www.docusign.net/API/3.0")]
public string Value { get; set; }
[XmlElement(ElementName = "CustomFieldType", Namespace = "http://www.docusign.net/API/3.0")]
public string CustomFieldType { get; set; }
}
}
Used following XML
<?xml version="1.0" encoding="utf-8"?>
<EnvelopeInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<RecipientStatuses>
<RecipientStatus>
<Type>Signer</Type>
<CustomFields>
<CustomField />
<CustomField />
<CustomField />
</CustomFields>
</RecipientStatus>
</RecipientStatuses>
</EnvelopeStatus>
</EnvelopeInfo>

Deserialize soap response with multiple namespaces

I am having a very hard time trying to deserialize the soap response below.
I assume its because of the multiple namespaces or maybe because of the complex type (Serialization Array)
Soapformatter throws an Object reference exception and other more manual deserializations are returning an empty object. At this point I can only assume that I am not tagging my object correctly. What is the correct way to build out the BatchResponse object below so that it can deserialize from this response?
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">https://example.com/operations/fetch/BatchResponse</a:Action>
</s:Header>
<s:Body>
<BatchResponse xmlns="https://example.com/operations">
<BatchResult xmlns:b="https://example.com/responses" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<b:FailureMessages xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true" />
<b:FailureType i:nil="true" />
<b:ProcessedSuccessfully>true</b:ProcessedSuccessfully>
<b:SessionId>1961810</b:SessionId>
<b:TotalPages>38</b:TotalPages>
</BatchResult>
</BatchResponse>
</s:Body>
</s:Envelope>
Also assuming Soapformatter continues to throw exceptions - what is the correct way to "xpath" to the BatchResponse object so that I can extract and deserialize?
Thanks
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication131
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class Envelope
{
[XmlElement(ElementName = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Header header { get; set; }
[XmlElement(ElementName = "Body", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Body body { get; set; }
}
[XmlRoot(ElementName = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class Header
{
[XmlElement(ElementName = "Action", Namespace = "http://www.w3.org/2005/08/addressing")]
public Action action { get; set; }
}
[XmlRoot(ElementName = "Action", Namespace = "http://www.w3.org/2005/08/addressing")]
public class Action
{
[XmlAttribute(AttributeName = "mustUnderstand", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public int mustUnderstand { get; set;}
[XmlText]
public string value { get;set;}
}
[XmlRoot(ElementName = "Body", Namespace = "")]
public class Body
{
[XmlElement(ElementName = "BatchResponse", Namespace = "https://example.com/operations")]
public BatchResponse batchResponse { get; set; }
}
[XmlRoot(ElementName = "BatchResponse", Namespace = "https://example.com/operations")]
public class BatchResponse
{
[XmlElement(ElementName = "BatchResult", Namespace = "https://example.com/operations")]
public BatchResult batchResult { get; set; }
}
[XmlRoot(ElementName = "BatchResult", Namespace = "https://example.com/operations")]
public class BatchResult
{
[XmlElement(ElementName = "FailureMessages", Namespace = "https://example.com/responses")]
public string failureMessages { get; set; }
[XmlElement(ElementName = "FailureType", Namespace = "https://example.com/responses")]
public string failureType { get; set; }
[XmlElement(ElementName = "ProcessedSuccessfully", Namespace = "https://example.com/responses")]
public Boolean processedSuccessfully { get; set; }
[XmlElement(ElementName = "SessionId", Namespace = "https://example.com/responses")]
public string sessionId { get; set; }
[XmlElement(ElementName = "TotalPages", Namespace = "https://example.com/responses")]
public int totalPages { get; set; }
}
}
you can use local-name() to ignore the namespace in xpath
//*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='BatchResponse']

Deserialization of Arrays in XML response

I'm still struggling with deserialization of XML containing arrays of items.
The response I want to deserialize:
<ns1:OperationResult xmlns:ns1="http://xxxx.com">
<done>false</done>
<errorEntities>
<elements>
<entityID>100014</entityID>
<entityType>GROUP</entityType>
<errors>
<errorCode>INVALID_DATA</errorCode>
<errorMessage>s: d3f62887-a2a3-4cde-8f8b-09812a7bd011ed8d385e-f4c4-4fae-9a4b-1ba405db54b6-MessageTemplate:{k2.constraints.numberFormat.length}|length:5|; </errorMessage>
</errors>
</elements>
</errorEntities>
</ns1:OperationResult>
And this is my corresponding class:
[XmlRootAttribute(Namespace = "http://xxxx.", IsNullable = false, ElementName = "OperationResult")]
public class GroupCreateUpdateResult
{
[XmlElement(ElementName = "done")]
public string done { get; set; }
[XmlElement(ElementName = "errorEntities")]
public ErrorEntities errorEntities { get; set; }
public bool hasErrors => done == "true" ? true : false;
}
[XmlRoot(ElementName = "errorEntities")]
public class ErrorEntities
{
[XmlElement(ElementName = "elements")]
public List<ErrorElements> elements { get; } = new List<ErrorElements>();
}
[XmlRoot(ElementName = "elements")]
public class ErrorElements
{
[XmlElement(ElementName = "entityId")]
public string entityId { get; set; }
[XmlElement(ElementName = "entityType")]
public string entityType { get; set; }
[XmlElement(ElementName = "errors")]
Errors errors { get; set; }
}
[XmlRoot(ElementName = "errors")]
public class Errors
{
[XmlElement(ElementName = "errorCode")]
public string errorCode { get; set; }
[XmlElement(ElementName = "errorMessage")]
public string errorMessage { get; set; }
}
I have already a method deserializing my responses. Actually I am struggling with this specific one. Alle others without arrays are working fine.
What I finally get is this:
Any advice is highly appreciated.
You have a few issues
1) The namespace in the xml and the classes have to be the same
2) The tags names in the classes are case sensitive so you have to make sure the spelling is correct (Upper/Lower Case)
3) The class object have to be public otherwise the tags are ignored.
4) Where there are no namespaces in XML (and parent has a namespace) you need the empty string for the namespaces
See corrected code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(GroupCreateUpdateResult));
GroupCreateUpdateResult group = (GroupCreateUpdateResult)serializer.Deserialize(reader);
}
}
[XmlRootAttribute(Namespace = "http://com.f24.soap.fwi.schema", IsNullable = false, ElementName = "OperationResult")]
public class GroupCreateUpdateResult
{
[XmlElement(ElementName = "done", Namespace = "")]
public string done { get; set; }
[XmlElement(ElementName = "errorEntities", Namespace = "")]
public ErrorEntities errorEntities { get; set; }
//public bool hasErrors => done == "true" ? true : false;
}
[XmlRoot(ElementName = "errorEntities")]
public class ErrorEntities
{
[XmlElement(ElementName = "elements", Namespace = "")]
public List<ErrorElements> elements { get; set;}
}
[XmlRoot(ElementName = "elements")]
public class ErrorElements
{
[XmlElement(ElementName = "entityID")]
public string entityId { get; set; }
[XmlElement(ElementName = "entityType")]
public string entityType { get; set; }
[XmlElement(ElementName = "errors", Namespace = "")]
public Errors errors { get; set; }
}
[XmlRoot(ElementName = "errors")]
public class Errors
{
[XmlElement(ElementName = "errorCode")]
public string errorCode { get; set; }
[XmlElement(ElementName = "errorMessage")]
public string errorMessage { get; set; }
}
}

How to deserialize xml parent root attribute

I have following XML Structure:
<ComputationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" DataType="DimX">
<Mode Name="M1">
<Area>
<Point PointNumber="3" Speed="127" Power="1455" Value="-2" />
<Point PointNumber="2" Speed="127" Power="1396.8" Value="2" />
<Point PointNumber="3" Speed="101.6" Power="1164" Value="-2" />
</Area>
</Mode>
</ComputationData>
In below class structure I am not able to get the value of Datatype which is available in XMl root(ComputationData).
For following XML I have created following class structure:
[Serializable]
[XmlRoot("ComputationData")]
public class FullLoadPerformanceGrid
{
/// <summary>
/// Name of the performance data type of this grid, e.g. Bsfc, tEat...
/// </summary>
[XmlElement(ElementName = "ComputationData", Type =
typeof(PerformanceType))]
public PerformanceType DataType { get; set; }
/// <summary>
/// List of available <see cref="FullLoadPerformanceMode"/>
/// </summary>
[XmlElement("Mode", Type = typeof(FullLoadPerformanceMode))]
public List<FullLoadPerformanceMode> Modes { get; set; }
}
[Serializable]
[XmlRoot("ComputationData")]
public class PerformanceType
{
public int Id { get; set; }
[DataMember(Name = "DataType")]
[XmlAttribute("DataType")]
public string DataType { get; set; }
public int Type { get; set; }
}
Can anyone help me with the class structure that how should I define the PerformanceType(DataType)?
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(FullLoadPerformanceGrid));
FullLoadPerformanceGrid load = (FullLoadPerformanceGrid)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "ComputationData", Namespace = "")]
public class FullLoadPerformanceGrid
{
[XmlAttribute("DataType", Namespace = "")]
public string DataType { get; set; }
[XmlElement(ElementName = "Mode", Namespace = "")]
public Mode mode { get; set; }
}
[XmlRoot(ElementName = "Mode", Namespace = "" )]
public class Mode
{
[XmlAttribute("Name", Namespace = "")]
public string name { get; set; }
[XmlArray("Area", Namespace = "")]
[XmlArrayItem("Point", Namespace = "")]
public List<Point> points { get; set; }
}
[XmlRoot(ElementName = "Point", Namespace = "")]
public class Point
{
[XmlAttribute("PointNumber", Namespace = "")]
public int pointNumber { get; set; }
[XmlAttribute("Speed", Namespace = "")]
public decimal speed { get; set; }
[XmlAttribute("Power", Namespace = "")]
public decimal power { get; set; }
[XmlAttribute("Value", Namespace = "")]
public int value { get; set; }
}
}

WCF receives empty model from XML

We have a WCF service with defined class (class was autogenerated from XML using http://xmltocsharp.azurewebsites.net/ ):
namespace CRMtoQLM.DAL
{
[Serializable]
[DataContract(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[DataMember]
public Body Body { get; set; }
[XmlAttribute(AttributeName = "soapenv", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Soapenv { get; set; }
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Xsd { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Xsi { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[DataContract(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "notifications", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public Notifications Notifications { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "notifications", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataContract(Namespace = "http://soap.sforce.com/2005/09/outbound")]
public class Notifications
{
[XmlElement(ElementName = "OrganizationId", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string OrganizationId { get; set; }
[XmlElement(ElementName = "ActionId", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string ActionId { get; set; }
[XmlElement(ElementName = "SessionId", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string SessionId { get; set; }
[XmlElement(ElementName = "EnterpriseUrl", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string EnterpriseUrl { get; set; }
[XmlElement(ElementName = "PartnerUrl", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string PartnerUrl { get; set; }
[XmlElement(ElementName = "Notification", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public Notification Notification { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
[DataMember]
public string Xmlns { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "Notification", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataContract(Namespace = "http://soap.sforce.com/2005/09/outbound")]
public class Notification
{
[XmlElement(ElementName = "Id", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string Id { get; set; }
[XmlElement(ElementName = "sObject", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public SObject SObject { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "sObject", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataContract(Namespace = "http://soap.sforce.com/2005/09/outbound")]
public class SObject
{
[XmlElement(ElementName = "Id", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Id { get; set; }
[XmlElement(ElementName = "Asset_Account_City__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Account_City__c { get; set; }
[XmlElement(ElementName = "Asset_Account_Country__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Account_Country__c { get; set; }
[XmlElement(ElementName = "Asset_Account_Name__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Account_Name__c { get; set; }
[XmlElement(ElementName = "Asset_Customer_ID__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Customer_ID__c { get; set; }
[XmlElement(ElementName = "Expiration_Date__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Expiration_Date__c { get; set; }
[XmlElement(ElementName = "License__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string License__c { get; set; }
[XmlElement(ElementName = "Reader_Code__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Reader_Code__c { get; set; }
[XmlElement(ElementName = "Reader_Quantity__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Reader_Quantity__c { get; set; }
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
[DataMember]
public string Type { get; set; }
[XmlAttribute(AttributeName = "sf", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Sf { get; set; }
}
}
IService.cs defined like this:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "Test",
RequestFormat = WebMessageFormat.Xml)]
//[XmlSerializerFormat]
string Test(Envelope parameter);
and implementation:
public string Test(Envelope parameter)
{
return "";
}
but "parameter" in Test function contains NULL objects. I know there is a problem with XML deserialization but can't figure out where exactly.
EDIT: this is the request that I'm sending via Postman
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<OrganizationId>123456</OrganizationId>
<ActionId>123456</ActionId>
<SessionId>123456</SessionId>
<EnterpriseUrl>https://eu8.salesforce.com/</EnterpriseUrl>
<PartnerUrl>https://eu8.salesforce.com/</PartnerUrl>
<Notification>
<Id>123456</Id>
<sObject xsi:type="sf:Asset" xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
<sf:Id>123456</sf:Id>
<sf:Asset_Account_City__c>123456</sf:Asset_Account_City__c>
<sf:Asset_Account_Country__c>123456</sf:Asset_Account_Country__c>
<sf:Asset_Account_Name__c>123456</sf:Asset_Account_Name__c>
<sf:Asset_Customer_ID__c>123456</sf:Asset_Customer_ID__c>
<sf:Expiration_Date__c>123456</sf:Expiration_Date__c>
<sf:License__c>123456</sf:License__c>
<sf:Reader_Code__c>123456</sf:Reader_Code__c>
<sf:Reader_Quantity__c>123456</sf:Reader_Quantity__c>
</sObject>
</Notification>
</notifications>
</soapenv:Body>
</soapenv:Envelope>
SOAP-based bindings unpack the SOAP envelope for you, so you shouldn't need to define the SOAP envelope types. The WebHttpBinding which you say you're using, which doesn't know anything about SOAP, would expect that the contract type (the argument of your service method IService.Test) would match the entire HTTP body, so I see the logic of what you're doing, however I don't think it's necessary to work against the framework like this.
To fix this scenario do a couple of things:
amend your implementation of IService.Test to take an argument of type Notifications
string Test(Notifications notifications)
amend the service config to specify an HTTP-based SOAP binding, probably BasicHttpBinding
<endpoint address="/relativeaddress/" binding="basicHttpBinding" ... />
I think a SOAP binding will probably ignore WebInvokeAttribute, but to be on the safe side, remove it. It's superfluous for a SOAP binding because SOAP is always POST.
I don't think you need to delete the Envelope and Body types but they won't do anything if they're not referenced, which is what you want. WCF bindings understand the SOAP envelope natively and don't need it to be specified, it's the content of the SOAP Body element that types need to be provided for.
Your XML sample contains a single instance of Notification under Notifications but the name implies that this child element could be repeating - if it is, I don't think the generated classes will work for you because the Notifications class has a singular Notification property - the generator you linked to has no way to know this so I don't fault it in any way. I added a copy of the Notification element as a sibling and ran it through again - this time it generated a list member:
[XmlElement(ElementName="Notification", Namespace="http://soap.sforce.com/2005/09/outbound")]
public List<Notification> Notification { get; set; }
You can use the xsd.exe tool supplied with Visual Studio (I think) to generate classes - see the documentation. I wouldn't be surprised if that web tool is driving this behind the scenes but I'd trust xsd.exe to generate classes that have the best possible compliance with what WCF expects of them.

Categories

Resources