Get attribute values to the XML-File - c#

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...

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;
}
}

XML element name with special characters while serialising

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>

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.

XML deserialization in C# returns an empty object

I have a problem here about deserialization. I have a XML file that I need to deserialize into a class that I get from a Service reference. I know how to deserialize a XML file, but when I try to deserialize this file I get a empty class object. I don't understand why is it doing that.
The XML files content looks like this:
<?xml version="1.0" encoding="UTF-8" ?><iVAZFile xmlns="http://www.v.lt/c/i/iv">
<FileDescription>
<FileVersion>i1.3.3</FileVersion>
<FileDateCreated>2016-11-07T12:28:32</FileDateCreated>
<SoftwareCompanyName>otechnika"</SoftwareCompanyName>
<SoftwareName>Eita</SoftwareName>
<SoftwareVersion>2016.9</SoftwareVersion>
<CreatorRegistrationNumber>123060356</CreatorRegistrationNumber>
</FileDescription>
</iVAZFile>
The class looks like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1590.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.v.lt/c/i/iv")]
public partial class FileDescription : object, System.ComponentModel.INotifyPropertyChanged {
private string fileVersionField;
private System.DateTime fileDateCreatedField;
private string softwareCompanyNameField;
private string softwareNameField;
private string softwareVersionField;
private ulong creatorRegistrationNumberField;
public FileDescription() {
this.fileVersionField = "iVAZ1.3.3";
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public string FileVersion {
get {
return this.fileVersionField;
}
set {
this.fileVersionField = value;
this.RaisePropertyChanged("FileVersion");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public System.DateTime FileDateCreated {
get {
return this.fileDateCreatedField;
}
set {
this.fileDateCreatedField = value;
this.RaisePropertyChanged("FileDateCreated");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=2)]
public string SoftwareCompanyName {
get {
return this.softwareCompanyNameField;
}
set {
this.softwareCompanyNameField = value;
this.RaisePropertyChanged("SoftwareCompanyName");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string SoftwareName {
get {
return this.softwareNameField;
}
set {
this.softwareNameField = value;
this.RaisePropertyChanged("SoftwareName");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=4)]
public string SoftwareVersion {
get {
return this.softwareVersionField;
}
set {
this.softwareVersionField = value;
this.RaisePropertyChanged("SoftwareVersion");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=5)]
public ulong CreatorRegistrationNumber {
get {
return this.creatorRegistrationNumberField;
}
set {
this.creatorRegistrationNumberField = value;
this.RaisePropertyChanged("CreatorRegistrationNumber");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
And the method that I use to populate the class:
using (MemoryStream memoryStream = new MemoryStream())
{
using (BinaryWriter binWriter = new BinaryWriter(memoryStream, Encoding.UTF8))
{
string filep = File.ReadAllText("test.xml");
binWriter.Write(filep);
memoryStream.Seek(2, SeekOrigin.Begin);
using (StreamReader streamReader = new StreamReader(memoryStream))
{
using (XmlReader reader = XmlReader.Create(streamReader))
{
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "FileDescription";
xRoot.IsNullable = false;
XmlSerializer serializer = new XmlSerializer(typeof(FileDescription),xRoot);
FileDescription dsc = new FileDescription();
dsc=(FileDescription)serializer.Deserialize(reader);
}
}
}
}
A few additional comment to say what I also tried:
I made my own class that looked the same as the one from the service reference and added a new parameter [XmlRoot(ElementName="FileDescription"),XmlType("FileDescription")]
then the deserilization worked on my class.
Tried adding values by hand without deserilization that worked fine as well so there's no problem with the service code.
Also when I'm deserializing the xml I remove <iVAZFile xmlns="http://www.v.lt/c/i/iv"> and </iVAZFIle> because when deserializing it will throw and exception was not expecting .
And lastly a few words I cannot change the service reference class and I need to use that class for later so I cannot make my own.
The difference is the namespace - per the XmlType attribute on your FileDescription class, the namespace is http://www.v.lt/c/i/iv. This applies to all child elements of the FileDescription. The root namespace is whatever you configure via your XmlRootAttribute or by the constructor that takes a default namespace.
As I suggested, the easiest way to debug this sort of issue is to do the reverse - serialise an object and see what it looks like. As you can see in this fiddle the output at present would look like this. This is why you're not getting any error (as the root class matches), but all the child elements in the XML you're deserialising are in the wrong namespace.
<FileDescription>
<FileVersion xmlns="http://www.v.lt/c/i/iv">iVAZ1.3.3</FileVersion>
<FileDateCreated xmlns="http://www.v.lt/c/i/iv">0001-01-01T00:00:00</FileDateCreated>
<CreatorRegistrationNumber xmlns="http://www.v.lt/c/i/iv">0</CreatorRegistrationNumber>
</FileDescription>
If you specify the same namespace for the root as in this fiddle, the output looks like this:
<FileDescription xmlns="http://www.v.lt/c/i/iv">
<FileVersion>iVAZ1.3.3</FileVersion>
<FileDateCreated>0001-01-01T00:00:00</FileDateCreated>
<CreatorRegistrationNumber>0</CreatorRegistrationNumber>
</FileDescription>
You need to keep the namespace in your amended document. You can see this works in this fiddle.
(Posted on behalf of the OP).
The problem is solved thanks to Charles Mager. The problem was I had to add the namespace to every value in my XML so it would have to look like this:
<FileDescription>
<FileVersion xmlns="http://www.v.lt/c/i/iv">i1.3.3</FileVersion>
<FileDateCreated xmlns="http://www.v.lt/c/i/iv">2016-11-07T12:28:32</FileDateCreated>
<SoftwareCompanyName xmlns="http://www.v.lt/c/i/iv">otechnika"</SoftwareCompanyName>
<SoftwareName xmlns="http://www.v.lt/c/i/iv">Eita</SoftwareName>
<SoftwareVersion xmlns="http://www.v.lt/c/i/iv">2016.9</SoftwareVersion>
<CreatorRegistrationNumber xmlns="http://www.v.lt/c/i/iv">123060356</CreatorRegistrationNumber>
</FileDescription>
Now it works fine, thanks for the help.

Serialize to xml using a class with multiple classes

I am using an asp.net and C# to serialize some entered data using a class. This class was generated from an xsd file. I am using this class to generate an xml file. I am struggling to understand how I can reference all these classes and serialize it to one xml file.
Here is my class code. It is in a separate file within my project:
namespace Ce
{
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.0.30319.33440.
//
public partial class AddRequest
{
private CDocument cDocumentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public CDocument CDocument
{
get
{
return this.cDocumentField;
}
set
{
this.cDocumentField = value;
}
}
}
public partial class CDocument
{
private CaseA caseAField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public CaseA CaseA
{
get
{
return this.caseAField;
}
set
{
this.caseAField = value;
}
}
}
public partial class CaseA
{
public string dCTextField;
private string dLField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public string DCText
{
get
{
return this.dCTextField;
}
set
{
this.dCTextField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public string DLU
{
get
{
return this.dLField;
}
set
{
this.dLField = value;
}
}
}
}
To serialize I have this in my code-behind in a button click event:
protected void CaseSubmitButton_Click(object sender, EventArgs e)
{
CaseA CSerialize = new CaseA();
CSerialize.DCText = casetextboxt.text;
CSerialize.DLu = "\\app";
XmlSerializer Serializer = new XmlSerializer(typeof(CaseA));
StreamWriter Writer = new StreamWriter(Server.MapPath("~/XmlPackages/" + xmlPackageFilename));
Serializer.Serialize(Writer, CSerialize);
Serializer.Serialize(Writer, CSerialize);
}
With this button click event I get this xml format:
<?xml version="1.0" encoding="utf-8"?>
<CaseA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DCText>\apptest</DCText>
<DLU>\apptest</DLU>
</CaseA>
I would like to reference the other two classes to get:
<?xml version="1.0" encoding="utf-8"?>
<Addrequest>
<Cdocument>
<CaseA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DCText>\apptest</DCText>
<DLU>\apptest</DLU>
</CaseA>
</Cdocument>
</Addrequest>
You're serializing an instance of CaseA class, which is why you're only seeing members of CaseA in the output. You need to create an instance of AddRequest and serialize that as the root, something like this:
CaseA cSerialize = new CaseA();
cSerialize .DCText = casetextboxt.text;
cSerialize .DLu = "\\app";
CDocument document = new CDocument();
document.CaseA = cSerialize ;
AddRequest root = new AddRequest();
root.CDocument = document;
XmlSerializer serializer = new XmlSerializer(typeof(AddRequest), new Type[] { typeof(CDocument), typeof(CaseA) });
StreamWriter writer = new StreamWriter(Server.MapPath("~/XmlPackages/" + xmlPackageFilename));
serializer.Serialize(writer, root);
As a side note, please follow C# coding standards for naming your local variables :)

Categories