XML element name with special characters while serialising - c#

While serialising the object to the XML I use the attribute convention like [XmlElement("MyData:Pool1")] for me it does the job but the XML looks like
<_x005C_MyData_x003A_Pool1 >
I presume it convert to the colon or any special chars to some other formats, I tried changing with backslash, # and $ signs preceding to the string, but it didn't helped me.
Any suggestions apart from using string / regex replace ?
private void Serlise(Interface request)
{
var xsSubmit = new XmlSerializer(typeof(Interface));
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
var xml = "";
using (var encoder = new CustomEncoder())
{
using (var writer = XmlWriter.Create(encoder))
{
xsSubmit.Serialize(writer, request,ns);
xml = encoder.ToString();
}
}
File.WriteAllText(#"output.xml", xml);
}
Below is the class to be serialised
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.foo1.com/bar/test/")]
[System.Xml.Serialization.XmlRootAttribute(ElementName = "Pool", Namespace = "http://www.foo1.com/bar/test/", IsNullable = false)]
public partial class Root
{
private Tester adminField;
private string versionField;
[XmlElement("Test:Pool1")]
public Tester Admin
{
get
{
return this.adminField;
}
set
{
this.adminField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Version
{
get
{
return this.versionField;
}
set
{
this.versionField = value;
}
}
}
NOTE : Slightly adjusted namespace & class name on XML due to NDA
<?xml version="1.0" encoding="utf-8"?><q1:MydataPool Version="1" xmlns:q1="http://www.foo1.com/bar/test"><q1:Data Id ="000123" Function="Hi"><q1:Hello Test="Abcd" /></q1:Data></q1:MydataPool>

Specify the namespace in the property attribute:
[XmlElement("Pool1", Namespace = "url")]
public Tester Admin
Set a prefix for this namespace:
var ns = new XmlSerializerNamespaces();
ns.Add("MyData", "url");
In the result, you will get
<MyData:Pool1>

Related

XML Parsing with C# from a service

I am having a bad time trying to consume an XML service.
This is my code to consume the service (it is a public service so you can consume it):
using( var client = new HttpClient() )
{
client.DefaultRequestHeaders
.Accept
.Add( new MediaTypeWithQualityHeaderValue( "text/xml" ) );
var request = new HttpRequestMessage( HttpMethod.Get, "https://gee.bccr.fi.cr/Indicadores/Suscripciones/WS/wsindicadoreseconomicos.asmx/ObtenerIndicadoresEconomicosXML?Indicador=317&FechaInicio=20%2F04%2F2022&FechaFinal=20%2F04%2F2022&Nombre=Jos%C3%A9+Miguel+Torres+G%C3%B3mez&SubNiveles=N&CorreoElectronico=josetorres%40outlook.com&Token=2LOEU2EM8O" );
var returnedXml = client.SendAsync( request ).Result.Content.ReadAsStringAsync().Result;
Console.WriteLine( returnedXml );
}
The response I get from there is the following, adding the console screenshot due to it returns special scape chars:
<string xmlns="http://ws.sdde.bccr.fi.cr">
<Datos_de_INGC011_CAT_INDICADORECONOMIC>
<INGC011_CAT_INDICADORECONOMIC>
<COD_INDICADORINTERNO>317</COD_INDICADORINTERNO>
<DES_FECHA>2022-04-20T00:00:00-06:00</DES_FECHA>
<NUM_VALOR>650.10000000</NUM_VALOR>
</INGC011_CAT_INDICADORECONOMIC>
</Datos_de_INGC011_CAT_INDICADORECONOMIC>
</string>
This is the class I use to try to deserialize:
public class Datos_de_INGC011_CAT_INDICADORECONOMIC
{
public INGC011_CAT_INDICADORECONOMIC INGC011_CAT_INDICADORECONOMIC { get; set; }
}
public class INGC011_CAT_INDICADORECONOMIC
{
public int COD_INDICADORINTERNO { get; set; }
public DateTime DES_FECHA { get; set; }
public double NUM_VALOR { get; set; }
}
But when I try to Deserialize the string I get the error: There is an error in XML document. Data at the root level is invalid. And due to I don't use to work with XML data I am stocked here.
The problem is that the "outer" XML is a wrapper for the "inner" one, which is encoded as text node for the first. In other words, that's NOT a single document, rather two different documents nested.
My guess is about the outer one, which looks like a descriptor for what itself contains.
That being said, you can extract what you need in a two-step job:
using System;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using( var client = new HttpClient() )
{
client.DefaultRequestHeaders
.Accept
.Add( new MediaTypeWithQualityHeaderValue( "text/xml" ) );
var request = new HttpRequestMessage( HttpMethod.Get, " ... " );
var returnedXml = client.SendAsync( request ).Result.Content.ReadAsStringAsync().Result;
Console.WriteLine( returnedXml );
//create a XML DOM from the returned payload
XDocument xdoc_outer = XDocument.Parse(returnedXml );
//extract the inner document as text (being a true-text node)
string inner_text = (string)xdoc_outer.Root;
//deserialize the text straight to a POCO shaped accordingly
var serializer = new XmlSerializer(typeof(Datos_de_INGC011_CAT_INDICADORECONOMIC));
using (var reader = XmlReader.Create(new StringReader(inner_text)))
{
//'result' contains the deserialized POCO, unless something went wrong!
var result = (Datos_de_INGC011_CAT_INDICADORECONOMIC)serializer.Deserialize(reader);
}
}
Probably there are better yet compact ways to achieve the same result, but I think that's pretty clear.
As final note, I reccomend to use async/await than accessing the data through the Result property.
Looks like the problem you are having is because of the outer element you have in your xml (string)
You can use one of the ways mentioned here (https://stackoverflow.com/a/19613934/3377344) in this post to create your class.
I used the paste special method shown there and here is the class I was able to generate:
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://ws.sdde.bccr.fi.cr")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.sdde.bccr.fi.cr", IsNullable = false)]
public partial class #string
{
private stringDatos_de_INGC011_CAT_INDICADORECONOMIC datos_de_INGC011_CAT_INDICADORECONOMICField;
/// <remarks/>
public stringDatos_de_INGC011_CAT_INDICADORECONOMIC Datos_de_INGC011_CAT_INDICADORECONOMIC
{
get
{
return this.datos_de_INGC011_CAT_INDICADORECONOMICField;
}
set
{
this.datos_de_INGC011_CAT_INDICADORECONOMICField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://ws.sdde.bccr.fi.cr")]
public partial class stringDatos_de_INGC011_CAT_INDICADORECONOMIC
{
private stringDatos_de_INGC011_CAT_INDICADORECONOMICINGC011_CAT_INDICADORECONOMIC iNGC011_CAT_INDICADORECONOMICField;
/// <remarks/>
public stringDatos_de_INGC011_CAT_INDICADORECONOMICINGC011_CAT_INDICADORECONOMIC INGC011_CAT_INDICADORECONOMIC
{
get
{
return this.iNGC011_CAT_INDICADORECONOMICField;
}
set
{
this.iNGC011_CAT_INDICADORECONOMICField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://ws.sdde.bccr.fi.cr")]
public partial class stringDatos_de_INGC011_CAT_INDICADORECONOMICINGC011_CAT_INDICADORECONOMIC
{
private ushort cOD_INDICADORINTERNOField;
private System.DateTime dES_FECHAField;
private decimal nUM_VALORField;
/// <remarks/>
public ushort COD_INDICADORINTERNO
{
get
{
return this.cOD_INDICADORINTERNOField;
}
set
{
this.cOD_INDICADORINTERNOField = value;
}
}
/// <remarks/>
public System.DateTime DES_FECHA
{
get
{
return this.dES_FECHAField;
}
set
{
this.dES_FECHAField = value;
}
}
/// <remarks/>
public decimal NUM_VALOR
{
get
{
return this.nUM_VALORField;
}
set
{
this.nUM_VALORField = value;
}
}
}
Once you have that class ready, you should be able to get the deserialize to work.
I used something like this:
class Program
{
static void Main(string[] args)
{
string myxml = $#"
<string xmlns = ""http://ws.sdde.bccr.fi.cr"">
<Datos_de_INGC011_CAT_INDICADORECONOMIC>
<INGC011_CAT_INDICADORECONOMIC>
<COD_INDICADORINTERNO>317</COD_INDICADORINTERNO>
<DES_FECHA>2022-04-20T00:00:00-06:00</DES_FECHA>
<NUM_VALOR>650.10000000</NUM_VALOR>
</INGC011_CAT_INDICADORECONOMIC>
</Datos_de_INGC011_CAT_INDICADORECONOMIC>
</string>
";
var res = XMLToObject(myxml, typeof(#string));
}
public static object XMLToObject(string xml, Type type, string xmlnamespace = "http://ws.sdde.bccr.fi.cr")
{
object result = null;
using (var stream = new StringReader(xml))
{
using(var reader = new XmlTextReader(stream))
{
var xmlRootAttr = new XmlRootAttribute();
xmlRootAttr.Namespace = xmlnamespace;
xmlRootAttr.ElementName = type.Name;
var serializer = new XmlSerializer(type, xmlRootAttr);
result = serializer.Deserialize(reader);
}
}
return result;
}
}

Getting null in nested elements when deserializing xml

I'm deserializing my xml which is string, into my classes.
Problem is that part of nested child elements or their attributes return null.
Here is my deserialize function:
public static T DeSerialize<T>(this string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StringReader(xml))
{
T result = (T)serializer.Deserialize(reader);
return result;
}
}
Here are my classes:
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.specifiedcompany.com/API")]
public partial class VideoGames
{
private GameType[] typesField;
private Platform platformField;
private string memoField;
[System.Xml.Serialization.XmlArray("Types", Order = 0)]
[System.Xml.Serialization.XmlArrayItem("Data", IsNullable = false)]
public GameType[] Types
{
get
{
return this.typesField;
}
set
{
this.typesField= value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Platform", Order = 1)]
public Platform Platform
{
get
{
return this.platformField;
}
set
{
this.platformField= value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Memo
{
get
{
return this.memoField;
}
set
{
this.memoField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class Platform
{
private decimal compressedField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public decimal Compressed
{
get
{
return this.compressedField;
}
set
{
this.compressedField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class GameType
{
private Code[] codeField;
private string nameField;
[System.Xml.Serialization.XmlArrayAttribute("Code", Order = 0)]
[System.Xml.Serialization.XmlArrayItemAttribute("Category", IsNullable = false)]
public Code[] Code
{
get
{
return this.codeField;
}
set
{
this.codeField= value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Name
{
get
{
return this.nameField;
}
set
{
this.nameField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class Code
{
private string textField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Text
{
get
{
return this.textField;
}
set
{
this.textField= value;
}
}
}
Here is the xml:
<VideoGames Memo="1">
<Types>
<Data Name="RPG">
<Code>
<Category Text="TestingData"/>
</Code>
</Data>
</Types>
<Platform Compressed="3.2876"/>
</VideoGames>
And I'm using deserialize like this:
string xml = "";//xml string above.
VideoGames a = xml.DeSerialize<VideoGames>();
I expect every property in class will have value, but only Memo in VideoGames has value, others are null.
For example: a.Types is null, but a.Memo is "1".
I have tried all related questions searched by this topic, and none of them work.
Note:
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
I have checked this xDoc, it loaded perfectly, nothing was lost.
The easiest way to diagnose problems in XML deserialization is to serialize to XML and compare the observed XML with the required XML. Usually the problem will be immediately apparent.
If I create and serialize an instance of VideoGames as follows:
var root = new VideoGames
{
Types = new []
{
new GameType
{
Name = "RPG",
Code = new []
{
new Code { Text = "TestingData" },
}
},
},
Platform = new Platform { Compressed = 3.2876m, },
};
var xml = root.GetXml(omitStandardNamespaces: true);
Console.WriteLine(xml);
Using the following extension method:
public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
{
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
{
ns = new XmlSerializerNamespaces();
ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
}
using (var textWriter = new StringWriter())
{
var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes.
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
}
}
Then the output is:
<VideoGames>
<Types xmlns="http://www.specifiedcompany.com/API">
<Data Name="RPG">
<Code>
<Category Text="TestingData" />
</Code>
</Data>
</Types>
<Platform Compressed="3.2876" xmlns="http://www.specifiedcompany.com/API" />
</VideoGames>
Demo fiddle here.
As you can see, the child elements <Types> and <Platform> are all serialized in an XML namespace, specifically http://www.specifiedcompany.com/API.
Your deserialization fails because, in the sample XML, these elements are not in any namespace.
Why is this happening? It's because all your classes including VideoGames have an XmlTypeAttribute attribute applied that specifies a Namespace:
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.specifiedcompany.com/API")]
public partial class VideoGames
{
}
What this attribute does is to specify that by default, all properties of the type should be serialized into the specified namespace. (Compare with XmlRootAttribute which specifies how the root element <VideoGames> itself, rather than just its children, is to be serialized.)
If you don't want that, remove the XmlTypeAttribute.Namespace setting from your c# classes VideoGames, Platform, GameType and Code (demo fiddle #2 here). If you do want that, modify your XML to include the required namespace as shown in the output XML in this answer.
I ran into this same issue recently, where it turns out if a single field in a nested XML object was null or missing, or the value in the field couldn't deserialize to the specific type, the List representing the nested elements would just return null.
I tried all sorts of attributes for the fields, trying IsNullable and a bunch of other recommended attributes as mentioned here on stackoverflow, nothing helped.
To fix this, I ended up changing all the fields in my class the XML is being deserialized to type of string.
Hope this helps someone.

Map XML tags with dot(.) to C# object

I have XML file which have some tags with dot(.), now i am using "StringWriter"
to Map XML data with C#, but i am not able to handle XML tags which have dot(.) in tag name like:- "Customer.Name", how can i map this with C# class.
I had give XmlElement with my class model, but still i am not getting values map with my class.
Can any one give me suggestion.
[XmlElement(ElementName = "PARENTNAME")]
public string PARENTNAME { get; set; } //This is perfect mapped
[XmlElement(ElementName = "DISPLAYCONTACT.CONTACTNAME")]
public string DISPLAYCONTACTCONTACTNAME { get; set; } // This is not mapped
[XmlElement(ElementName = "DISPLAYCONTACT.COMPANYNAME")]
public string DISPLAYCONTACTCOMPANYNAME { get; set; }
Convert XML to C#
XmlDocument doc = new XmlDocument();
doc.LoadXml(custome‌​rString);
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
doc.WriteTo(xw);
String XmlString = sw.ToString();
string xmlToJson = JsonConvert.SerializeXmlNode(doc);
var deserialized = JsonConvert.SerializeXmlNode(doc);
var custome‌​r = new CusGetResIn();
custome‌​r= JsonConvert.DeserializeObject<CusGetResIn>(deserialized);
Also Tried:-
XmlSerializer serializer = new XmlSerializer(typeof(CusGetResIn));
MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(XmlString));
CusGetResIn resultingMessage = (CusGetResIn)serializer.Deserialize(memStream);
XML:-
<?xml version="1.0" encoding="UTF-8"?>
<response>
<control>
<status>success</status>
<senderid>Intacct_ISB</senderid>
<controlid>17/12/2018</controlid>
<uniqueid>false</uniqueid>
<dtdversion>3.0</dtdversion>
</control>
<operation>
<authentication>
<status>success</status>
<userid>vinit1</userid>
<companyid>FASTMORE-trial</companyid>
<locationid></locationid>
<sessiontimestamp>2018-12-19T00:41:15-08:00</sessiontimestamp>
</authentication>
<result>
<status>success</status>
<function>readByQuery</function>
<controlid>testFunctionId</controlid>
<data listtype="customer" count="31" totalcount="31" numremaining="0" resultId="">
<customer>
<RECORDNO>5</RECORDNO>
<CUSTOMERID>CUST-00101</CUSTOMERID>
<NAME>Sun Microsystems - EBC</NAME>
<ENTITY>CCUST-00101</ENTITY>
<PARENTKEY></PARENTKEY>
<PARENTID></PARENTID>
<PARENTNAME></PARENTNAME>
<DISPLAYCONTACT.CONTACTNAME>Sun Microsystems - EBC(CCUST-00101)</DISPLAYCONTACT.CONTACTNAME>
<DISPLAYCONTACT.COMPANYNAME>Sun Microsystems - EBC</DISPLAYCONTACT.COMPANYNAME>
<DISPLAYCONTACT.PREFIX></DISPLAYCONTACT.PREFIX>
<DISPLAYCONTACT.FIRSTNAME></DISPLAYCONTACT.FIRSTNAME>
<DISPLAYCONTACT.LASTNAME></DISPLAYCONTACT.LASTNAME>
<DISPLAYCONTACT.INITIAL></DISPLAYCONTACT.INITIAL>
<DISPLAYCONTACT.PRINTAS>Sun Microsystems - Executive Briefing Center</DISPLAYCONTACT.PRINTAS>
<DISPLAYCONTACT.TAXABLE>true</DISPLAYCONTACT.TAXABLE>
<DISPLAYCONTACT.TAXGROUP></DISPLAYCONTACT.TAXGROUP>
<DISPLAYCONTACT.PHONE1></DISPLAYCONTACT.PHONE1>
<DISPLAYCONTACT.PHONE2></DISPLAYCONTACT.PHONE2>
<DISPLAYCONTACT.CELLPHONE></DISPLAYCONTACT.CELLPHONE>
<DISPLAYCONTACT.PAGER></DISPLAYCONTACT.PAGER>
<DISPLAYCONTACT.FAX></DISPLAYCONTACT.FAX>
<DISPLAYCONTACT.EMAIL1>sevans#intacct.com</DISPLAYCONTACT.EMAIL1>
<DISPLAYCONTACT.EMAIL2></DISPLAYCONTACT.EMAIL2>
<DISPLAYCONTACT.URL1></DISPLAYCONTACT.URL1>
<DISPLAYCONTACT.URL2></DISPLAYCONTACT.URL2>
<DISPLAYCONTACT.VISIBLE>true</DISPLAYCONTACT.VISIBLE>
<DISPLAYCONTACT.MAILADDRESS.ADDRESS1>1245 Williams Lane</DISPLAYCONTACT.MAILADDRESS.ADDRESS1>
<DISPLAYCONTACT.MAILADDRESS.ADDRESS2></DISPLAYCONTACT.MAILADDRESS.ADDRESS2>
<DISPLAYCONTACT.MAILADDRESS.CITY>San Jose</DISPLAYCONTACT.MAILADDRESS.CITY>
<DISPLAYCONTACT.MAILADDRESS.STATE>CA</DISPLAYCONTACT.MAILADDRESS.STATE>
<DISPLAYCONTACT.MAILADDRESS.ZIP>95112</DISPLAYCONTACT.MAILADDRESS.ZIP>
<DISPLAYCONTACT.MAILADDRESS.COUNTRY>USA</DISPLAYCONTACT.MAILADDRESS.COUNTRY>
<DISPLAYCONTACT.MAILADDRESS.COUNTRYCODE></DISPLAYCONTACT.MAILADDRESS.COUNTRYCODE>
<DISPLAYCONTACT.MAILADDRESS.LATITUDE></DISPLAYCONTACT.MAILADDRESS.LATITUDE>
<DISPLAYCONTACT.MAILADDRESS.LONGITUDE></DISPLAYCONTACT.MAILADDRESS.LONGITUDE>
<DISPLAYCONTACT.STATUS>active</DISPLAYCONTACT.STATUS>
<TERMNAME>2/10 Net30</TERMNAME>
<TERMVALUE>2:10:1#30#1%:W:</TERMVALUE>
<CUSTREPID>EMP-002</CUSTREPID>
<CUSTREPNAME>Joanna Drake</CUSTREPNAME>
<RESALENO></RESALENO>
<TAXID></TAXID>
<CREDITLIMIT></CREDITLIMIT>
<TOTALDUE>3525172.72</TOTALDUE>
<COMMENTS></COMMENTS>
<ACCOUNTLABEL></ACCOUNTLABEL>
<ARACCOUNT>4000</ARACCOUNT>
<ARACCOUNTTITLE>Sales</ARACCOUNTTITLE>
<LAST_INVOICEDATE>10/01/2012</LAST_INVOICEDATE>
<LAST_STATEMENTDATE></LAST_STATEMENTDATE>
<DELIVERY_OPTIONS>Print#~#E-Mail</DELIVERY_OPTIONS>
<TERRITORYID></TERRITORYID>
<SHIPPINGMETHOD>Delivery</SHIPPINGMETHOD>
<CUSTTYPE>Corporate</CUSTTYPE>
<GLGRPKEY></GLGRPKEY>
<GLGROUP></GLGROUP>
<PRICESCHEDULE></PRICESCHEDULE>
<DISCOUNT></DISCOUNT>
<PRICELIST></PRICELIST>
<VSOEPRICELIST></VSOEPRICELIST>
<CURRENCY></CURRENCY>
<CONTACTINFO.CONTACTNAME></CONTACTINFO.CONTACTNAME>
<CONTACTINFO.PREFIX></CONTACTINFO.PREFIX>
<CONTACTINFO.FIRSTNAME></CONTACTINFO.FIRSTNAME>
<CONTACTINFO.INITIAL></CONTACTINFO.INITIAL>
<CONTACTINFO.LASTNAME></CONTACTINFO.LASTNAME>
<CONTACTINFO.COMPANYNAME></CONTACTINFO.COMPANYNAME>
<CONTACTINFO.PRINTAS></CONTACTINFO.PRINTAS>
<CONTACTINFO.PHONE1></CONTACTINFO.PHONE1>
<CONTACTINFO.PHONE2></CONTACTINFO.PHONE2>
<CONTACTINFO.CELLPHONE></CONTACTINFO.CELLPHONE>
<CONTACTINFO.PAGER></CONTACTINFO.PAGER>
<CONTACTINFO.FAX></CONTACTINFO.FAX>
<CONTACTINFO.EMAIL1></CONTACTINFO.EMAIL1>
<CONTACTINFO.EMAIL2></CONTACTINFO.EMAIL2>
<CONTACTINFO.URL1></CONTACTINFO.URL1>
<CONTACTINFO.URL2></CONTACTINFO.URL2>
<CONTACTINFO.VISIBLE></CONTACTINFO.VISIBLE>
<CONTACTINFO.MAILADDRESS.ADDRESS1></CONTACTINFO.MAILADDRESS.ADDRESS1>
<CONTACTINFO.MAILADDRESS.ADDRESS2></CONTACTINFO.MAILADDRESS.ADDRESS2>
<CONTACTINFO.MAILADDRESS.CITY></CONTACTINFO.MAILADDRESS.CITY>
<CONTACTINFO.MAILADDRESS.STATE></CONTACTINFO.MAILADDRESS.STATE>
<CONTACTINFO.MAILADDRESS.ZIP></CONTACTINFO.MAILADDRESS.ZIP>
<CONTACTINFO.MAILADDRESS.COUNTRY></CONTACTINFO.MAILADDRESS.COUNTRY>
<CONTACTINFO.MAILADDRESS.COUNTRYCODE></CONTACTINFO.MAILADDRESS.COUNTRYCODE>
<SHIPTO.CONTACTNAME></SHIPTO.CONTACTNAME>
<SHIPTO.PREFIX></SHIPTO.PREFIX>
<SHIPTO.FIRSTNAME></SHIPTO.FIRSTNAME>
<SHIPTO.INITIAL></SHIPTO.INITIAL>
<SHIPTO.LASTNAME></SHIPTO.LASTNAME>
<SHIPTO.COMPANYNAME></SHIPTO.COMPANYNAME>
<SHIPTO.PRINTAS></SHIPTO.PRINTAS>
<SHIPTO.TAXABLE></SHIPTO.TAXABLE>
<SHIPTO.TAXGROUP></SHIPTO.TAXGROUP>
<SHIPTO.PHONE1></SHIPTO.PHONE1>
<SHIPTO.PHONE2></SHIPTO.PHONE2>
<SHIPTO.CELLPHONE></SHIPTO.CELLPHONE>
<SHIPTO.PAGER></SHIPTO.PAGER>
<SHIPTO.FAX></SHIPTO.FAX>
<SHIPTO.EMAIL1></SHIPTO.EMAIL1>
<SHIPTO.EMAIL2></SHIPTO.EMAIL2>
<SHIPTO.URL1></SHIPTO.URL1>
<SHIPTO.URL2></SHIPTO.URL2>
<SHIPTO.VISIBLE></SHIPTO.VISIBLE>
<SHIPTO.MAILADDRESS.ADDRESS1></SHIPTO.MAILADDRESS.ADDRESS1>
<SHIPTO.MAILADDRESS.ADDRESS2></SHIPTO.MAILADDRESS.ADDRESS2>
<SHIPTO.MAILADDRESS.CITY></SHIPTO.MAILADDRESS.CITY>
<SHIPTO.MAILADDRESS.STATE></SHIPTO.MAILADDRESS.STATE>
<SHIPTO.MAILADDRESS.ZIP></SHIPTO.MAILADDRESS.ZIP>
<SHIPTO.MAILADDRESS.COUNTRY></SHIPTO.MAILADDRESS.COUNTRY>
<SHIPTO.MAILADDRESS.COUNTRYCODE></SHIPTO.MAILADDRESS.COUNTRYCODE>
<BILLTO.CONTACTNAME></BILLTO.CONTACTNAME>
<BILLTO.PREFIX></BILLTO.PREFIX>
<BILLTO.FIRSTNAME></BILLTO.FIRSTNAME>
<BILLTO.INITIAL></BILLTO.INITIAL>
<BILLTO.LASTNAME></BILLTO.LASTNAME>
<BILLTO.COMPANYNAME></BILLTO.COMPANYNAME>
<BILLTO.PRINTAS></BILLTO.PRINTAS>
<BILLTO.TAXABLE></BILLTO.TAXABLE>
<BILLTO.TAXGROUP></BILLTO.TAXGROUP>
<BILLTO.PHONE1></BILLTO.PHONE1>
<BILLTO.PHONE2></BILLTO.PHONE2>
<BILLTO.CELLPHONE></BILLTO.CELLPHONE>
<BILLTO.PAGER></BILLTO.PAGER>
<BILLTO.FAX></BILLTO.FAX>
<BILLTO.EMAIL1></BILLTO.EMAIL1>
<BILLTO.EMAIL2></BILLTO.EMAIL2>
<BILLTO.URL1></BILLTO.URL1>
<BILLTO.URL2></BILLTO.URL2>
<BILLTO.VISIBLE></BILLTO.VISIBLE>
<BILLTO.MAILADDRESS.ADDRESS1></BILLTO.MAILADDRESS.ADDRESS1>
<BILLTO.MAILADDRESS.ADDRESS2></BILLTO.MAILADDRESS.ADDRESS2>
<BILLTO.MAILADDRESS.CITY></BILLTO.MAILADDRESS.CITY>
<BILLTO.MAILADDRESS.STATE></BILLTO.MAILADDRESS.STATE>
<BILLTO.MAILADDRESS.ZIP></BILLTO.MAILADDRESS.ZIP>
<BILLTO.MAILADDRESS.COUNTRY></BILLTO.MAILADDRESS.COUNTRY>
<BILLTO.MAILADDRESS.COUNTRYCODE></BILLTO.MAILADDRESS.COUNTRYCODE>
<STATUS>active</STATUS>
<ONETIME>false</ONETIME>
<CUSTMESSAGEID></CUSTMESSAGEID>
<ONHOLD>false</ONHOLD>
<PRCLST_OVERRIDE>C</PRCLST_OVERRIDE>
<OEPRCLSTKEY></OEPRCLSTKEY>
<OEPRICESCHEDKEY></OEPRICESCHEDKEY>
<ENABLEONLINECARDPAYMENT>true</ENABLEONLINECARDPAYMENT>
<ENABLEONLINEACHPAYMENT>true</ENABLEONLINEACHPAYMENT>
<VSOEPRCLSTKEY></VSOEPRCLSTKEY>
<WHENMODIFIED>12/18/2018 16:07:40</WHENMODIFIED>
<ARINVOICEPRINTTEMPLATEID></ARINVOICEPRINTTEMPLATEID>
<OEQUOTEPRINTTEMPLATEID></OEQUOTEPRINTTEMPLATEID>
<OEORDERPRINTTEMPLATEID></OEORDERPRINTTEMPLATEID>
<OELISTPRINTTEMPLATEID></OELISTPRINTTEMPLATEID>
<OEINVOICEPRINTTEMPLATEID></OEINVOICEPRINTTEMPLATEID>
<OEADJPRINTTEMPLATEID></OEADJPRINTTEMPLATEID>
<OEOTHERPRINTTEMPLATEID></OEOTHERPRINTTEMPLATEID>
<WHENCREATED>01/01/1970 00:00:00</WHENCREATED>
<CREATEDBY></CREATEDBY>
<MODIFIEDBY>1</MODIFIEDBY>
<OBJECTRESTRICTION>Unrestricted</OBJECTRESTRICTION>
<DISPLAYCONTACTKEY>38</DISPLAYCONTACTKEY>
<CONTACTKEY></CONTACTKEY>
<SHIPTOKEY></SHIPTOKEY>
<BILLTOKEY></BILLTOKEY>
<CUSTREPKEY>2</CUSTREPKEY>
<SHIPVIAKEY>1</SHIPVIAKEY>
<TERRITORYKEY></TERRITORYKEY>
<TERMSKEY>1</TERMSKEY>
<ACCOUNTLABELKEY></ACCOUNTLABELKEY>
<ACCOUNTKEY>25</ACCOUNTKEY>
<CUSTTYPEKEY>1</CUSTTYPEKEY>
<PRICESCHEDULEKEY></PRICESCHEDULEKEY>
<OFFSETGLACCOUNTNO></OFFSETGLACCOUNTNO>
<OFFSETGLACCOUNTNOTITLE></OFFSETGLACCOUNTNOTITLE>
<ADVBILLBY></ADVBILLBY>
<ADVBILLBYTYPE></ADVBILLBYTYPE>
<SUPDOCID></SUPDOCID>
<MEGAENTITYKEY></MEGAENTITYKEY>
<MEGAENTITYID></MEGAENTITYID>
<MEGAENTITYNAME></MEGAENTITYNAME>
<RESTRICTEDLOCATIONS></RESTRICTEDLOCATIONS>
<RESTRICTEDDEPARTMENTS></RESTRICTEDDEPARTMENTS>
</customer></data>
</result>
</operation>
</response>
Please help me.
Quick test shows XmlSerializer can handle this pretty easily
Test class:
[XmlRoot]
public class Test
{
[XmlElement(ElementName="Foo.Alpha")]
public string Alpha {get;set;}
[XmlElement(ElementName="Foo.Beta")]
public string Beta {get;set;}
}
Example method:
private static void Main()
{
var src = #"<Test>
<Foo.Alpha>value 1</Foo.Alpha>
<Foo.Beta>value 2</Foo.Beta>
</Test>";
using (var sreader = new StringReader(src))
using (var reader = XmlReader.Create(sreader))
{
var serializer = new XmlSerializer(typeof(Test));
var test = (Test)serializer.Deserialize(reader);
Console.WriteLine(test.Alpha);
Console.WriteLine(test.Beta);
}
}
Update: since the XML document you are processing is very large, you should consider what you actually need to do. If you need to manipulate the entire document as objects then the approach taken in JP Hellemons's answer may be the way to go. If you are only interested in certain fields, then it may be better to load the XML into an XDocument or XmlDocument and extract the fields you are interested in from that, or even write a forward-only parser using XmlReader to do the same thing.
I have pasted your XML in an XMLFile1.xml and pasted it in Visual Studio to generate classes, so this will be a lot of autogenerated code... warning
could not fit auto gen code...
Body is limited to 30000 characters; you entered 93977
Full code here:
https://pastebin.com/VxzNUjsv
Smaller version:
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<RECORDNO>5</RECORDNO>
<CUSTOMERID>CUST-00101</CUSTOMERID>
<PARENTNAME>parent</PARENTNAME>
<DISPLAYCONTACT.CONTACTNAME>Sun Microsystems - EBC(CCUST-00101)</DISPLAYCONTACT.CONTACTNAME>
<DISPLAYCONTACT.COMPANYNAME>Sun Microsystems - EBC</DISPLAYCONTACT.COMPANYNAME>
</customer>
and C# code:
class Program
{
static void Main(string[] args)
{
using (var sreader = new StringReader(File.ReadAllText(#"C:\Users\JP\source\repos\soXmlParsing\soXmlParsing\XMLFile1.xml")))
using (var reader = XmlReader.Create(sreader))
{
var serializer = new XmlSerializer(typeof(customer));
var test = (customer)serializer.Deserialize(reader);
Console.WriteLine(test.PARENTNAME);
Console.WriteLine(test.DISPLAYCONTACTCONTACTNAME);
}
}
}
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class customer
{
private byte rECORDNOField;
private string cUSTOMERIDField;
private string pARENTNAMEField;
private string dISPLAYCONTACTCONTACTNAMEField;
private string dISPLAYCONTACTCOMPANYNAMEField;
/// <remarks/>
public byte RECORDNO
{
get
{
return this.rECORDNOField;
}
set
{
this.rECORDNOField = value;
}
}
/// <remarks/>
public string CUSTOMERID
{
get
{
return this.cUSTOMERIDField;
}
set
{
this.cUSTOMERIDField = value;
}
}
/// <remarks/>
public string PARENTNAME
{
get
{
return this.pARENTNAMEField;
}
set
{
this.pARENTNAMEField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DISPLAYCONTACT.CONTACTNAME")]
public string DISPLAYCONTACTCONTACTNAME
{
get
{
return this.dISPLAYCONTACTCONTACTNAMEField;
}
set
{
this.dISPLAYCONTACTCONTACTNAMEField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DISPLAYCONTACT.COMPANYNAME")]
public string DISPLAYCONTACTCOMPANYNAME
{
get
{
return this.dISPLAYCONTACTCOMPANYNAMEField;
}
set
{
this.dISPLAYCONTACTCOMPANYNAMEField = value;
}
}
}

XML changes after Serialization

I noticed that my xml changes after serialization. e.g.
* the ns in the start of the Message element disappears
* xmlns:ns attribute becomes xmlns
* there are new attributes added in Message element - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" and xmlns:xsd="http://www.w3.org/2001/XMLSchema"
* new attribute in Header element - xmlns
How can I keep the original form of the xml and prevent these attributes from being added?
Here's how the original XML looks like:
<?xml version="1.0" encoding="UTF-8"?>
<ns:Message xmlns:ns="http://example.com">
<Header version="1.0">
<Sender>3015207400109</Sender>
<Receiver>8711200999903</Receiver>
<MessageID>000D2613F64AC021ED783C084735EC78E53</MessageID>
<CreationDateTime>2017-03-21T08:00:47Z</CreationDateTime>
</Header>
</ns:Message>
And here's the xml after it has been serialized:
<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com">
<Header version="1.0" xmlns="">
<Sender>3015207400109</Sender>
<Receiver>8711200999903</Receiver>
<MessageID>000D2613F64AC021ED783C084735EC78E53</MessageID>
<CreationDateTime>2017-03-21T08:00:47Z</CreationDateTime>
</Header>
</Message>
The code below is the (generated) class that represents the Message xml.
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://example.com")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://example.com", IsNullable = false)]
public partial class Message
{
private Header headerField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public Header Header
{
get
{
return this.headerField;
}
set
{
this.headerField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Header
{
private ulong senderField;
private ulong receiverField;
private string messageIDField;
private System.DateTime creationDateTimeField;
private decimal versionField;
/// <remarks/>
public ulong Sender
{
get
{
return this.senderField;
}
set
{
this.senderField = value;
}
}
/// <remarks/>
public ulong Receiver
{
get
{
return this.receiverField;
}
set
{
this.receiverField = value;
}
}
/// <remarks/>
public string MessageID
{
get
{
return this.messageIDField;
}
set
{
this.messageIDField = value;
}
}
/// <remarks/>
public System.DateTime CreationDateTime
{
get
{
return this.creationDateTimeField;
}
set
{
this.creationDateTimeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public decimal version
{
get
{
return this.versionField;
}
set
{
this.versionField = value;
}
}
}
The two XML files you show are semantically identical. Thus, I'd recommend not worrying about the fact that XmlSerializer inserts XML standard namespaces or chooses a different prefixing scheme than was used in the original file.
If, for whatever reason, you must suppress output of the standard namespaces and must preserve the prefixing scheme of the original file, here's what you can do.
Firstly, to omit the xsi and xsd namespaces at the root level, follow the instructions from Omitting all xsi and xsd namespaces when serializing an object in .NET?:
var s = new XmlSerializer(objectToSerialize.GetType());
var ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);
Next, in order to keep the original form of the xml you must first somehow capture the actual XML namespaces and prefixes encountered while reading the file and save them in the Message class somewhere for reuse later. Luckily XmlSerializer does support this: you can add an XmlSerializerNamespaces valued public property or field to Message and mark it with [XmlNamespaceDeclarations]. This member will now capture namespaces encountered during deserialization, and cause those namespaces to be added back during serialization.
Putting these two ideas together, you can modify your Message type as follows:
public partial class Message
{
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces XmlFileNamespaces { get; set; }
/// <summary>
/// returns a XmlSerializerNamespaces to use when serializing a Message as the root XML object.
/// If Message was previously deserialized from XML, the actual namespaces observed will be returned.
/// Otherwise, a default will be returned that suppresses output of the xmlns:xsi and xmlns:xsd namespace attributes.
/// </summary>
[XmlIgnore]
public XmlSerializerNamespaces XmlRootNamespaces
{
get
{
if (XmlFileNamespaces != null)
return XmlFileNamespaces;
var xmlNamespaces = new XmlSerializerNamespaces();
xmlNamespaces.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
// xmlNamespaces.Add("ns", "http://example.com"); // Or, if you prefer, add this namespace as well as disabling xmlns:xsi and xmlns:xsd.
return xmlNamespaces;
}
}
}
And serialize from and to XML as follows:
var message = xml.LoadFromXml<Message>();
var reserializedXml = message.GetXml(message.XmlRootNamespaces);
Using the following extension methods:
public static class XmlSerializationHelper
{
public static T LoadFromXml<T>(this string xmlString)
{
using (StringReader reader = new StringReader(xmlString))
{
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
}
public static string GetXml<T>(this T obj, XmlSerializerNamespaces ns)
{
using (var textWriter = new Utf8StringWriter())
{
var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes.
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
}
}
}
// http://stackoverflow.com/questions/3862063/serializing-an-object-as-utf-8-xml-in-net
public class Utf8StringWriter : StringWriter
{
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
Prototype fiddle.

Get attribute values to the XML-File

I got a issue with XML, and write some information on a XML-file.
I got several xsd-files describing my XML. I created one big .cs-file with "xsd/c testfile1.xsd testFile2.xsd..." etc. And everything went nice and looks good.
But if I take one created class i.e. testfile1.xsd, it looks like
"<xs:complexType name="Header">" and inside that one there is this some ordinary xs:element and stuff, but also this: "<xs:attribute name="version" default="1.0.0.0"/>". This is translated to:
"public Header() {
this.versionField = "1.0.0.0";}"
in the generated class 'Header'. And it got as well this field: private string versionField;
. (There is of course a couple of other private fields as well, but those works good.). So I create instances of all classes, fill them with data and write it as an XML-file with this:
- XmlSerializer XmlSerRoot = new XmlSerializer(typeof(RootInformation))
(the root of my xml!)
- StringWriterWithEncoding strWriter = new StringWriterWithEncoding(Encoding.GetEncoding("iso-8859-1"));
- XmlDocument documentInXML = new XmlDocument();
- XmlSerRoot.Serialize(strWriter, rootInformation); (Here is the XML, filled with values, and the Header.version got the value 1.0.0.0)
- string XmlString;
- XmlString = strWriter.ToString(); (Here I can look at the created xml when debugging in VS and now the version-information is gone)
- documentInXML.LoadXml(XmlString);
- documentInXML.Save(myPath);
But when I look at the xml-file this <Header> is not have anything like version. I want i to look like: <Header version="1.0.0.0">
I even tried to do it in code like:
Header header = new Header();
header.version = header.version;
and
with header.version = "1.0.0.0";
But still it's no version-text in the tag. All other tags got their value. Just this <Header> loose this extra information.
Does someone got a tip? There is a lot of places I need this to work. Everything else is just working fine.
Regards, /E
Here is an piece of example-code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
namespace TestAppXML
{
class Program
{
static void Main(string[] args)
{
RootInfo rootInfo = new RootInfo();
rootInfo.RootText = "This is the Root!";
Header header = new Header();
header.TestHeader = "This is HeaderText!";
rootInfo.Header = header;
XmlSerializer XmlSerRoot = new XmlSerializer(typeof(RootInfo));
StringWriterWithEncoding strWriter = new StringWriterWithEncoding(Encoding.GetEncoding("iso-8859-1"));
XmlDocument documentInXML = new XmlDocument();
XmlSerRoot.Serialize(strWriter, rootInfo);
string XmlString;
XmlString = strWriter.ToString();
documentInXML.LoadXml(XmlString);
strWriter.Close();
documentInXML.Save(#"C:\TestXml.xml");
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://acme.com")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://acme.com", IsNullable = false)]
public partial class RootInfo
{
private Header headerField;
private string rootTextField;
public Header Header
{
get { return this.headerField; }
set { this.headerField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(DataType = "normalizedString")]
public string RootText
{
get { return this.rootTextField; }
set { this.rootTextField = value; }
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://acme.com")]
public partial class Header
{
private string testHeaderField;
private string versionField;
public Header()
{
this.versionField = "1.0.0.0";
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "normalizedString")]
public string TestHeader
{
get { return this.testHeaderField; }
set { this.testHeaderField = value; }
}
[System.Xml.Serialization.XmlAttributeAttribute()]
[System.ComponentModel.DefaultValueAttribute("1.0.0.0")]
public string version
{
get { return this.versionField; }
set { this.versionField = value; }
}
}
class StringWriterWithEncoding : StringWriter
{
private Encoding MyEncoding;
public StringWriterWithEncoding(Encoding encoding)
: base()
{MyEncoding = encoding;}
public override Encoding Encoding
{
get{return MyEncoding;}
}
}
}
Nevermind, I think I knov the issue. It's because this xsd.exe creates 'DefaultValueAttribute' for those fields. That prevent this field to be in the xml. Maybe some xsd-switch could have done that, I dunno...

Categories