C# Xml Serialize Attribute Adding Custom Namespace - c#

I am trying to add namespace during Xml Serialization. So far I have added some of them but I am unable to add custom namespace using Xml serializer.
So far I have achieved this
<?xml version="1.0"?>
<manifest xmlns:xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2e" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2" xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xs" identifier="test" version="2">
<lom xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test lom" xmlns="http://ltsc.ieee.org/xsd/LOM" />
<resource adlcp:scormtype="sco" />
</manifest>
This is my Code
Manifest Class
[Serializable]
[XmlRoot(ElementName = "manifest")]
public class Manifest
{
/// <summary>
/// manifest root node
/// </summary>
[XmlAttribute(AttributeName = "identifier")]
public string Identifier { get; set; }
[XmlAttribute(AttributeName = "version")]
public string Version { get; set; }
//[XmlAttribute(AttributeName = "adlcp", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
//public string Adlcp = "http://www.adlnet.org/xsd/adlcp_rootv1p2";
[XmlAttribute(AttributeName = "schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string SchemaLocation = "http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xs";
[XmlElement(ElementName = "lom", Namespace = "http://ltsc.ieee.org/xsd/LOM")]
public Lom Lom { get; set; }
[XmlElement("resource")]
public Resource Resource { get; set; }
}
Lom Class
public class Lom
{
[XmlAttribute(AttributeName = "schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string SchemaLocation { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.imsproject.org/xsd/imscp_rootv1p1p2e")]
public string Xsi = "http://www.w3.org/2001/XMLSchema-instance";
}
Resource Class
public class Resource
{
[XmlAttribute(AttributeName = "scormtype", Namespace = "http://www.adlnet.org/xsd/adlcp_rootv1p2")]
public string ScormType { get; set; }
}
My serialization function like this
using (FileStream fs = new FileStream(filePath, FileMode.Create))
{
var xmlSerializer = new XmlSerializer(typeof(Manifest));
var ns = new XmlSerializerNamespaces();
ns.Add("xmlns", "http://www.imsproject.org/xsd/imscp_rootv1p1p2e");
ns.Add("adlcp", "http://www.adlnet.org/xsd/adlcp_rootv1p2");
ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
xmlSerializer.Serialize(fs, data, ns);
fs.Close();
}
I need output like this.
<?xml version="1.0"?>
<manifest
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
identifier="test" version="2"
xmlns:adlcp="test"
xsi:schemaLocation="test location"
**xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2"**>
<lom
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ltsc.ieee.org/xsd/LOM lom.xsd"
xmlns="http://ltsc.ieee.org/xsd/LOM" />
<resource adlcp:scormtype="sco"/>
</manifest>
what I am doing wrong?

Simply add a namspace serializer
var xmlSerializer = new XmlSerializer(typeof(Manifest), "http://www.w3.org/2001/XMLSchema-instance");
var ns = new XmlSerializerNamespaces();
ns.Add("xmlns", "http://www.w3.org/2001/XMLSchema-instance");
xmlSerializer.Serialize(fs, data, ns);
and if data is defined as
Manifest data = new Manifest()
{ Identifier = "test", Version = "2", Adlcp = "test", SchemaLocation = "test location" };
data.Resource = new Resource() { ScormType="sco" };
with an attribute
[XmlAttribute(AttributeName = "adlcp", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Adlcp { get; set; }
you'll get xmlns:adlcp="test" in the output
Same thing for
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Xsi = "http://www.w3.org/2001/XMLSchema-instance";
As well as
ns.Add("adlcp", "http://www.imsproject.org/xsd/Manifest/Adlcp");
with
[XmlAttribute(AttributeName = "scormtype", Namespace = "http://www.imsproject.org/xsd/Manifest/Adlcp")]
public string ScormType { get; set; }
to get a possible adlcp:scormtype="sco"
Add a namespace to the root class too, for example
[XmlRoot(ElementName = "manifest", Namespace = "http://www.imsproject.org/xsd/Manifest")]
public class Manifest

Related

How to get a list of values on a XML response?

I get from a webservice a XML like this:
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<Get_PersonResponse
xmlns="http://tempuri.org/">
<Get_PersonResult
xmlns:a="http://schemas.datacontract.org/example"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:LASTNAME>DOE</a:LASTNAME>
<a:EMAIL/>
<a:FIRSTNAME>JONH</a:FIRSTNAME>
<a:NUM_CARD/>
<a:ID_PERSON>12345456</a:ID_PERSON>
<a:PHONE/>
</Get_PersonResult>
<RESP_COMMENT>"Person found"</RESP_COMMENT>
</Get_PersonResponse>
</s:Body>
</s:Envelope>
I want to check if RESP_COMMENT is empty. Then if is not empty get all the values (a:FIRSTNAME, a:LASTNAME, etc)
I got the a:FIRSTNAME on the fiddle but I am not sure if I have to do a bucle for every single value or is a better way to do it:
https://dotnetfiddle.net/cOsX6s
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(output);
XmlNodeList nodeList = xmldoc.GetElementsByTagName("a:FIRSTNAME");
string lastname = string.Empty;
foreach (XmlNode node in nodeList)
{
firstname = node.InnerText;
Console.Write(firstname);
}
Try xml serialization :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication177
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
StringReader sReader = new StringReader(xml);
XmlReader xReader = XmlReader.Create(sReader);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(xReader);
}
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
}
public class Body
{
[XmlElement(ElementName = "Get_PersonResponse", Namespace = "http://tempuri.org/")]
public Get_PersonResponse Get_PersonResponse { get; set; }
}
public class Get_PersonResponse
{
[XmlElement(Namespace = "http://tempuri.org/")]
public string RESP_COMMENT { get; set; }
[XmlElement(ElementName = "Get_PersonResult", Namespace = "http://tempuri.org/")]
public Get_PersonResult Get_PersonResult { get; set; }
}
public class Get_PersonResult
{
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string LASTNAME { get;set;}
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string EMAIL { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string FIRSTNAME { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string NUM_CARD { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string ID_PERSON { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/example")]
public string PHONE { get; set; }
}
}
There should be a way to get this values using xpath. I have tried a few different things and it seems that the empty prefix on namespace xmlns="http://tempuri.org/" is causing problems, see the element Get_PersonResponse namespace attribute.
<Get_PersonResponse xmlns="http://tempuri.org/">
To overcome this problem we need to remove the namespace that is causing the problem before loading the xml.
using System;
using System.Xml;
public class Program
{
public static void Main()
{
string output = #"<s:Envelope
xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
<s:Body>
<Get_PersonResponse
xmlns=""http://tempuri.org/"">
<Get_PersonResult
xmlns:a=""http://schemas.datacontract.org/example""
xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
<a:LASTNAME>DOE</a:LASTNAME>
<a:EMAIL/>
<a:FIRSTNAME>JONH</a:FIRSTNAME>
<a:NUM_CARD/>
<a:ID_PERSON>12345456</a:ID_PERSON>
<a:PHONE/>
</Get_PersonResult>
<RESP_COMMENT>""Person found!""</RESP_COMMENT>
</Get_PersonResponse>
</s:Body>
</s:Envelope>";
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(output.Replace(#"xmlns=""http://tempuri.org/""", ""));
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmldoc.NameTable);
nsmgr.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("a", "http://schemas.datacontract.org/example");
var personResultNode = xmldoc.SelectSingleNode("//s:Envelope/s:Body/Get_PersonResponse/Get_PersonResult", nsmgr);
foreach (var nodes in personResultNode.ChildNodes)
{
var personAttribute = (XmlNode)nodes;
Console.WriteLine($"{personAttribute.LocalName}: {personAttribute.InnerText}");
}
Console.Read();
}
}
BTW: I have also tried to add an empty prefix for namespace xmlns="http://tempuri.org/" to the XmlNamespaceManager but that didn't help.

How to process the XML file having hierarchical structure to get the inner details

I have a large xml file with following structure.This is a snippet which contains many <xn:TestElement> nodes.
<?xml version="1.0" encoding="utf-8" ?>
<testDataFile
xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.615#configData"
xmlns:xn="http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm" xmlns:in="http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm">
<fileHeader fileFormatVersion="32.615 V6.3" vendorName="TestVendor"/>
<configData dnPrefix="">
<xn:SubNetwork id="ONRM_ROOT_MO">
<xn:SubNetwork id="RNC425">
<xn:TestElement id="DA_Test_place0">
<xn:attributes>
<xn:userLabel>DA_Test_place0</xn:userLabel>
</xn:attributes>
<in:InventoryUnit id="n/a">
<in:attributes>
<in:manufacturerData>ProductName=Non-subrack HW,SlotCount=0</in:manufacturerData>
</in:attributes>
<in:InventoryUnit id="0">
<in:attributes>
<in:vendorUnitTypeNumber>KRC11876/1_R4A</in:vendorUnitTypeNumber>
<in:manufacturerData>ProductName=RUS 02 B8</in:manufacturerData>
</in:attributes>
</in:InventoryUnit>
<in:InventoryUnit id="0">
<in:attributes>
<in:vendorUnitTypeNumber>test/1_R4A</in:vendorUnitTypeNumber>
</in:attributes>
</in:InventoryUnit>
</in:InventoryUnit>
<in:InventoryUnit id="n/a">
<in:attributes>
<in:manufacturerData>ProductName=Virtual subrack,SlotCount=2</in:manufacturerData>
</in:attributes>
<in:InventoryUnit id="1">
<in:attributes>
<in:vendorUnitTypeNumber>KDU127174/4_R2D/A</in:vendorUnitTypeNumber>
</in:attributes>
</in:InventoryUnit>
<in:InventoryUnit id="1">
<in:attributes>
<in:vendorUnitTypeNumber>KDU127174/4_R2D/B</in:vendorUnitTypeNumber>
<in:manufacturerData>ProductName=RUS 02 B7</in:manufacturerData>
</in:attributes>
</in:InventoryUnit>
</in:InventoryUnit>
</xn:TestElement>
<xn:TestElement id="DA_Test_place1">
</xn:TestElement>
</xn:SubNetwork>
</xn:SubNetwork>
</configData>
</testDataFile>
Now I want to process this xml get information like:
testelementname slotdata inventory unit number
------------------------------------------------------------------------------
DA_Test_place0 ProductName=Non-subrack HW,SlotCount=0 KRC11876/1_R4A
DA_Test_place0 ProductName=Non-subrack HW,SlotCount=0 test/1_R4A
DA_Test_place0 ProductName=Virtual subrack,SlotCount=2 KDU127174/4_R2D/A
DA_Test_place0 ProductName=Virtual subrack,SlotCount=2 KDU127174/4_R2D/B
How can I process this xml file and get information either in datatable or C# classes. I wrote the following code, but it got stuck with the hierarchy of xml
while (reader.Read())
{
if (reader.Name != "xn:TestElement")
{
reader.ReadToFollowing("xn:TestElement");
}
while (reader.NodeType == XmlNodeType.Element && reader.LocalName == "TestElement")
{
XElement elements = (XElement)XElement.ReadFrom(reader);
testelemenname = reader.GetAttribute("id");
slotdata = GetInventoryValue(elements, "manufacturerData");
invenotry unit number = GetInventoryValue(elements, "vendorUnitTypeNumber");
}
}
private static string GetInventoryValue(XElement pin, string input)
{
XElement manufacturerData = pin.Descendants().Where(a => a.Name.LocalName == input).FirstOrDefault();
if (manufacturerData != null)
{
return (string)manufacturerData;
}
}
EDIT
Heirarchy of XML changed a bit and added two level 'SubNetwork' node and one more node 'configData'and namespaces also changed,now i am not getting the result
You can achieve your desired result by using XDocument.
Here I created a sample console app for your demonstration purpose,
class Program
{
public static void Main(string[] args)
{
XDocument doc = XDocument.Load(#"Path to your xml file");
XNamespace ns = doc.Root.GetDefaultNamespace();
XNamespace xdt = "http://www.3gpp.org";
var result = doc.Descendants(ns + "TestElement")
.Elements(ns + "InventoryUnit")
.Elements(ns + "InventoryUnit")
.Select(x => new
{
test_element_name = x.AncestorsAndSelf(ns + "TestElement").FirstOrDefault()?.Attribute("id")?.Value,
slot_data = x.Ancestors(ns + "InventoryUnit").AncestorsAndSelf(ns + "InventoryUnit").FirstOrDefault().Element(ns + "attributes").Element(ns + "manufacturerData")?.Value,
invenotry_unit_number = x.Element(ns + "attributes").Element(ns + "vendorUnitTypeNumber")?.Value,
}).ToList();
//-----------Print result--------------
foreach (var item in result)
{
Console.WriteLine(item.test_element_name);
Console.WriteLine(item.slot_data);
Console.WriteLine(item.invenotry_unit_number);
Console.WriteLine();
}
Console.ReadLine();
}
}
Output:
Edit:
If your xml file size is too large and XDocument failed to parse it then you can try XmlSerializer like
XmlSerializer serializer = new XmlSerializer(new TestDataFile().GetType());
using (StringReader stringReader = new StringReader(File.ReadAllText(#"Path to your xml file")))
{
TestDataFile testDataFile = (TestDataFile)serializer.Deserialize(stringReader);
var result = testDataFile.ConfigData.SubNetwork.InnerSubNetwork.SelectMany(a => a.TestElement.SelectMany(x => x.InventoryUnit.SelectMany(y => y.IU
.Select(z => new { test_element_name = x.Id, slot_data = y.Attributes.ManufacturerData, invenotry_unit_number = z.Attributes.VendorUnitTypeNumber })))).ToList();
foreach (var item in result)
{
Console.WriteLine(item.test_element_name);
Console.WriteLine(item.slot_data);
Console.WriteLine(item.invenotry_unit_number);
Console.WriteLine();
}
}
And you need below class hierarchy to deserialize your xml,
[XmlRoot(ElementName = "fileHeader", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public class FileHeader
{
[XmlAttribute(AttributeName = "fileFormatVersion")]
public string FileFormatVersion { get; set; }
[XmlAttribute(AttributeName = "vendorName")]
public string VendorName { get; set; }
}
[XmlRoot(ElementName = "attributes", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public class Attributes
{
[XmlElement(ElementName = "userLabel", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public string UserLabel { get; set; }
[XmlElement(ElementName = "manufacturerData", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public string ManufacturerData { get; set; }
[XmlElement(ElementName = "vendorUnitTypeNumber", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public string VendorUnitTypeNumber { get; set; }
}
[XmlRoot(ElementName = "InventoryUnit", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public class InnerInventoryUnit
{
[XmlElement(ElementName = "attributes", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public Attributes Attributes { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "InventoryUnit", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public class InventoryUnit
{
[XmlElement(ElementName = "attributes", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public Attributes Attributes { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "InventoryUnit", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public List<InnerInventoryUnit> IU { get; set; }
}
[XmlRoot(ElementName = "TestElement", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
public class TestElement
{
[XmlElement(ElementName = "InventoryUnit", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.695#inventoryNrm")]
public List<InventoryUnit> InventoryUnit { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "SubNetwork", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
public class InnerSubNetwork
{
[XmlElement(ElementName = "TestElement", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
public List<TestElement> TestElement { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "SubNetwork", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
public class SubNetwork
{
[XmlElement(ElementName = "SubNetwork", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
public List<InnerSubNetwork> InnerSubNetwork { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "configData", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.615#configData")]
public class ConfigData
{
[XmlElement(ElementName = "SubNetwork", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.625#genericNrm")]
public SubNetwork SubNetwork { get; set; }
[XmlAttribute(AttributeName = "dnPrefix")]
public string DnPrefix { get; set; }
}
[XmlRoot(ElementName = "testDataFile", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.615#configData")]
public class TestDataFile
{
[XmlElement(ElementName = "fileHeader", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.615#configData")]
public FileHeader FileHeader { get; set; }
[XmlElement(ElementName = "configData", Namespace = "http://www.3gpp.org/ftp/specs/archive/32_series/32.615#configData")]
public ConfigData ConfigData { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
[XmlAttribute(AttributeName = "xn", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xn { get; set; }
[XmlAttribute(AttributeName = "in", Namespace = "http://www.w3.org/2000/xmlns/")]
public string In { get; set; }
}

C# .net 4.6 XmlSerializerNamespaces XmlSerializer output problem

I need the following output from Pojo classes to Xml.
It's .net 4.6.1, C#.
Problem is in the namespaces and the produced prefixes.
How can I get the node:
<blablubb:Message SOAP-ENV:mustUnderstand="1" xmlns:blablubb="urn:blablubb-com:schemas:blablubb">
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<blablubb:Message SOAP-ENV:mustUnderstand="1" xmlns:blablubb="urn:blablubb-com:schemas:blablubb">
<blablubb:Type>INET_TRANS</blablubb:Type>
<blablubb:Function>RECEIVE_CUSTOMER_ORDER</blablubb:Function>
<blablubb:Sender>CONNECT</blablubb:Sender>
<blablubb:Receiver>CONNECT</blablubb:Receiver>
<blablubb:SentAt>2018-08-30T10:43:37+02:00</blablubb:SentAt>
<blablubb:ExpiresAt>2018-09-30T10:43:37+02:00</blablubb:ExpiresAt>
</blablubb:Message>
</SOAP-ENV:Header>
<SOAP-ENV:Body><ORDERS xmlns="urn:blablubb-com:schemas:inbound_distribution_transactions_create_customer_order_request" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BUYER></BUYER>
<CONTACT_REFERENCE>OAK</CONTACT_REFERENCE>
<EAN_LOCATION_DELIVERY_ADDRESS>10901000</EAN_LOCATION_DELIVERY_ADDRESS>
<CURRENCY_CODE>EUR</CURRENCY_CODE>
<ORDER_DATE>2018-08-27T09:01:01</ORDER_DATE>
<OUR_CUSTOMER_NO>2</OUR_CUSTOMER_NO>
<SUPPLIER_ADDRESS_NO></SUPPLIER_ADDRESS_NO>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Pojos that get serialized:
SoapDocument:
[Serializable]
[XmlRoot("Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[XmlInclude(typeof(SoapHeader))]
public class SoapDocument {
[XmlElement("Header")]
public SoapHeader soapHeader { get; set; }
[XmlElement("Body",typeof(IfsOrdersXmlDocument))]
public object soapBody { get; set; }
}
SoapHeader :
[Serializable]
[XmlRoot("Header")]
[XmlInclude(typeof(SoapMessage))] // include type class IfsOrderLineXmlDocument
public class SoapHeader {
[XmlElement("Message", Namespace = "urn:blablubb-com:schemas:blablubb")]
public SoapMessage soapMessage { get; set; }
}
SoapBody :
[Serializable]
[XmlInclude(typeof(IfsXmlDocument)), XmlInclude(typeof(IfsOrdersXmlDocument))]
[SoapInclude(typeof(IfsXmlDocument)), SoapInclude(typeof(IfsOrdersXmlDocument))]
public class SoapBody {
[XmlElement("Body")]
public IfsXmlDocument soapBody { get; set; }
}
SoapMessage:
[Serializable]
//[XmlType("blablubb")]
[XmlRoot("Message", Namespace = "urn:blablubb-com:schemas:blablubb")]
public class SoapMessage {
[XmlElement("Type")]
public string Type { get; set; }
[XmlElement("Function")]
public string Function { get; set; }
[XmlElement("Sender")]
public string Sender { get; set; }
[XmlElement("Receiver")]
public string Receiver { get; set; }
[XmlElement("SentAt")]
public string SentAt { get; set; }
[XmlElement("ExpiresAt")]
public string ExpiresAt { get; set; }
}
Code that produces the Xml,
So the problem is in the namespaces and prefixes ......
XmlSerializerNamespaces ns = createSoapDocument();
XmlSerializer serializer = new XmlSerializer(typeof(HeinzApi.Soap.SoapDocument), new Type[] { typeof(IfsXmlDocument), typeof(IfsOrdersXmlDocument) });
FileStream fs = new FileStream(xmlTargetPath, FileMode.Create);
serializer.Serialize(fs, soapDocument, ns);
fs.Close();`
And this is what I get:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<Message xmlns="urn:blablubb-com:schemas:blablubb">
<Type>INET_TRANS</Type>
<Function>RECEIVE_CUSTOMER_ORDER</Function>
<Sender>CONNECT</Sender>
<Receiver>CONNECT</Receiver>
<SentAt>2018-01-03T10:43:37+02:00</SentAt>
<ExpiresAt>2018-08-02T10:43:37+02:00</ExpiresAt>
</Message>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
This is the createSoapDocument method that adds namespaces to the XmlSerializer Namespaces object:
private XmlSerializerNamespaces createSoapDocument() {
soapMessage.Type = "INET_TRANS";
soapMessage.Function = "RECEIVE_CUSTOMER_ORDER";
soapMessage.Sender = "CONNECT";
soapMessage.Receiver = "CONNECT";
soapMessage.SentAt = "2018-01-03T10:43:37+02:00";
soapMessage.ExpiresAt = "2018-08-02T10:43:37+02:00";
soapHeader.soapMessage = soapMessage;
soapDocument.soapHeader = soapHeader;
//soapDocument.soapBody = (IfsXmlDocument)targetXmlBaseDocument; ;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
ns.Add("blablubb", "urn:blablubb-com:schemas:blablubb");
return ns;
}
Edit: This is the result after adding the namespaces to XmlSerializerNamespaces:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:blablubb="urn:blablubb-com:schemas:blablubb" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<blablubb:Message>
<blablubb:Type>INET_TRANS</blablubb:Type>
<blablubb:Function>RECEIVE_CUSTOMER_ORDER</blablubb:Function>
<blablubb:Sender>CONNECT</blablubb:Sender>
<blablubb:Receiver>CONNECT</blablubb:Receiver>
<blablubb:SentAt>2018-01-03T10:43:37+02:00</blablubb:SentAt>
<blablubb:ExpiresAt>2018-08-02T10:43:37+02:00</blablubb:ExpiresAt>
</blablubb:Message>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
You need to tell the serializer about your blahblubb namespace by adding it to your XmlSerializerNamespaces object.
ns.Add("blablubb", "urn:bla-com:schemas:blablubb");
Don't forget to change
[XmlElement("Body")]
to
[XmlElement("Body", Namespace="urn:bla-com:schemas:blablubb")]

XML Deserialization Coming up NULL

My Deserializer executes without exception, but the resulting object is coming up with nulls. The source XML clearly shows values that for some reason are not being set in the target object. I can't for the life of me figure out why?
Source XML:
<soapenv:Fault xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode>soapenv:Client</faultcode>
<faultstring>Could not insert new row - duplicate value in a UNIQUE INDEX column (Unique Index:).</faultstring>
<detail>
<axlError>
<axlcode>-239</axlcode>
<axlmessage>Could not insert new row - duplicate value in a UNIQUE INDEX column (Unique Index:).</axlmessage>
<request>addRoutePartition</request>
</axlError>
</detail>
Class:
using System.Xml.Serialization;
namespace AXLClassLibrary
{
[XmlRoot(ElementName = "Fault", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Fault
{
[XmlElement(ElementName = "faultcode")]
public string Faultcode { get; set; }
[XmlElement(ElementName = "faultstring")]
public string Faultstring { get; set; }
[XmlElement(ElementName = "detail")]
public Detail Detail { get; set; }
[XmlAttribute(AttributeName = "soapenv", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soapenv { get; set; }
}
[XmlRoot(ElementName = "axlError")]
public class AxlError
{
[XmlElement(ElementName = "axlcode")]
public string Axlcode { get; set; }
[XmlElement(ElementName = "axlmessage")]
public string Axlmessage { get; set; }
[XmlElement(ElementName = "request")]
public string Request { get; set; }
}
[XmlRoot(ElementName = "detail")]
public class Detail
{
[XmlElement(ElementName = "axlError")]
public AxlError AxlError { get; set; }
}
}
Deserializer Code:
var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
XDocument xd = XDocument.Parse(resp);
XNamespace ns1 = "http://schemas.xmlsoap.org/soap/envelope/";
XNode faultXML = xd.Descendants(ns1 + "Fault").DescendantNodesAndSelf().First();
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "Fault";
xRoot.Namespace = "http://schemas.xmlsoap.org/soap/envelope/";
xRoot.IsNullable = false;
resp = faultXML.ToString();
Fault currentFault;
XmlSerializer serializer = new XmlSerializer(typeof(Fault), xRoot);
using (TextReader readFault = new StringReader(resp))
{
currentFault = (Fault)serializer.Deserialize(readFault);
}

How to Deserialize XML using DataContractSerializer

I'm trying to deserialize an xml document:
<?xml version="1.0"?>
<games xmlns = "http://serialize">
<game>
<name>TEST1</name>
<code>TESTGAME1</code>
<ugn>1111111</ugn>
<bets>
<bet>5,00</bet>
</bets>
</game>
<game>
<name>TEST2</name>
<code>TESTGAME2</code>
<ugn>222222</ugn>
<bets>
<bet>0,30</bet>
<bet>0,90</bet>
</bets>
</game>
</games>
.cs class:
namespace XmlParse
{
using System.Collections.Generic;
using System.Runtime.Serialization;
[DataContract(Namespace = "http://serialize")]
public class game
{
#region Public Properties
[DataMember]
public string name { get; set; }
[DataMember]
public string code { get; set; }
[DataMember]
public long ugn { get; set; }
[DataMember]
public List<decimal> bets { get; set; }
#endregion
}
[KnownType(typeof(game))]
[DataContract(Namespace = "http://serialize")]
public class games
{
#region Public Properties
[DataMember]
public List<game> game { get; set; }
#endregion
}
}
Main:
FileStream fs = new FileStream(Path.Combine(this.path, xmlDocumentName), FileMode.Open);
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(games));
// Deserialize the data and read it from the instance.
games deserializedPerson = (games)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
deserializedPerson shows count = 0
what gives?
I figured it out. Maybe there are other implementations but this works. For the life of me I couldn't find any examples that use List inside an object. Here is a working example:
XML document to parse:
<?xml version="1.0"?>
<games xmlns = "http://serialize">
<game>
<name>TEST1</name>
<code>TESTGAME1</code>
<ugn>1111111</ugn>
<bets>
<bet>5,00</bet>
</bets>
</game>
<game>
<name>TEST2</name>
<code>TESTGAME2</code>
<ugn>222222</ugn>
<bets>
<bet>0,30</bet>
<bet>0,90</bet>
</bets>
</game>
</games>
.cs class:
namespace XmlParse
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
[DataContract(Name = "game", Namespace = "")]
public class Game
{
[DataMember(Name = "name", Order = 0)]
public string Name { get; private set; }
[DataMember(Name = "code", Order = 1)]
public string Code { get; private set; }
[DataMember(Name = "ugn", Order = 2)]
public string Ugn { get; private set; }
[DataMember(Name = "bets", Order = 3)]
public Bets Bets { get; private set; }
}
[CollectionDataContract(Name = "bets", ItemName = "bet", Namespace = "")]
public class Bets : List<string>
{
public List<decimal> BetList
{
get
{
return ConvertAll(y => decimal.Parse(y, NumberStyles.Currency));
}
}
}
[CollectionDataContract(Name = "games", Namespace = "")]
public class Games : List<Game>
{
}
}
Read and parse xml document:
string fileName = Path.Combine(this.path, "Document.xml");
DataContractSerializer dcs = new DataContractSerializer(typeof(Games));
FileStream fs = new FileStream(fileName, FileMode.Open);
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
Games games = (Games)dcs.ReadObject(reader);
reader.Close();
fs.Close();

Categories

Resources