I have to interact with a repository of documents, where each document is inserted with metadata contained in an XML document.
Now, at some point, this metadata must be generated from scratch. I thought that using a class to create this XML will be the best solution.
I generate the class using the Developer Command Prompt, this is the result:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://example.com/metadata")]
[System.Xml.Serialization.XmlRootAttribute(ElementName = "Metadata", Namespace="http://example.com/metadata", IsNullable=false)]
public partial class XmlMetadata {
private System.Xml.XmlElement[] anyField;
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
}
This class shoud be able to generate XML documents like this:
<?xml version="1.0" encoding="utf-8"?>
<md:Metadata xmlns:md="http://example.com/metadata">
<md:Cert>0001</md:Cert>
<md:Model>Test</md:Model>
<md:Created>2015-05-21</md:Created>
</md:Metadata>
QUESTION 1: Is this class enough descriptive to generate this kind of XML documents? (Note the prefix on every tag and how every tag have a different name, also I must be able to insert any number of elements)
QUESTION 2: How I insert elements in an instance of this class? This elements have the form of a KeyValuePair, where the key represent the tag name.
QUESTION 3: How do I serialize this class into a stream and into a Base64 string from there?
Thanks in advance
I would do it like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlMetadata data = new XmlMetadata(){
elemements = new List<Element>(){
new Element(){ name = "cert", value = "0001"},
new Element(){ name = "model", value = "Test"},
new Element(){ name = "created", value = "2015-05-21"}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(XmlMetadata));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("md", "http://example.com/metadata");
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, data, ns);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(XmlMetadata));
XmlTextReader reader = new XmlTextReader(FILENAME);
XmlMetadata newData = (XmlMetadata)xs.Deserialize(reader);
}
}
[XmlRootAttribute(ElementName = "Metadata", Namespace = "http://example.com/metadata", IsNullable = false)]
public class XmlMetadata
{
[XmlElement(ElementName = "Element", Namespace = "http://example.com/metadata", IsNullable = false)]
public List<Element> elemements { get; set; }
}
[XmlRootAttribute(ElementName = "Element", Namespace = "http://example.com/metadata", IsNullable = false)]
public class Element
{
[XmlAttribute(AttributeName = "name",Namespace = "http://example.com/metadata")]
public string name {get; set; }
[XmlAttribute(AttributeName = "value", Namespace = "http://example.com/metadata")]
public string value { get; set; }
}
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlMetadata data = new XmlMetadata()
{
cert = "0001",
model = "Test",
created = DateTime.Parse("2015-05-21")
};
XmlSerializer serializer = new XmlSerializer(typeof(XmlMetadata));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("md", "http://example.com/metadata");
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, data, ns);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(XmlMetadata));
XmlTextReader reader = new XmlTextReader(FILENAME);
XmlMetadata newData = (XmlMetadata)xs.Deserialize(reader);
}
}
[XmlRootAttribute(ElementName = "Metadata", Namespace = "http://example.com/metadata", IsNullable = false)]
public class XmlMetadata
{
[XmlElement(ElementName = "Cert", Namespace = "http://example.com/metadata", IsNullable = false)]
public string cert {get;set;}
[XmlElement(ElementName = "Model", Namespace = "http://example.com/metadata", IsNullable = false)]
public string model {get;set;}
[XmlElement(ElementName = "Created", Namespace = "http://example.com/metadata", IsNullable = false)]
public DateTime created {get;set;}
}
}
Related
I need to make a api where in the request body there needs to be a CData object. All works exept that I cant figure out how to make my object serialze into a CData object. The project is written in the .net-framework.
I currently have the following code.
C#:
[XmlRoot(ElementName = "DATA")]
public class DATA
{
[XmlElement(ElementName = "ID")]
public int ID { get; set; }
[XmlElement(ElementName = "NAME")]
public string NAME{ get; set; }
}
[XmlRoot(ElementName = "NewDataSet")]
public class CDataSet
{
[XmlElement(ElementName = "DATA")]
public DATA data{ get; set; }
}
How the xml needs to look after:
<![CDATA[
<NewDataSet>
<DATA>
<ID>007</ID>
<NAME>John</NAME>
</DATA>
</NewDataSet>
]]>
I can make it working by serializing normally by making a request to this function:
public static string SerializeObject<T>(this T toSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
}
Than manual adding the CData parts around it.
However my boss wants it make it work without manually adding the parts.
Please note I'm very new to C#.
Any step in the right direction will help. Thanks!
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
CDataSet data = new CDataSet()
{
data = new DATA() { ID = "007", NAME = "John" }
};
MemoryStream stream = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(stream, settings);
XmlSerializer serializer = new XmlSerializer(typeof(CDataSet));
serializer.Serialize(writer, data);
writer.Flush();
writer.Close();
stream.Position = 0;
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
string xml = Encoding.UTF8.GetString(buffer);
string output = string.Format("<![CDATA[\n{0}\n]]>", xml);
}
}
[XmlRoot(ElementName = "DATA", Namespace = "")]
public class DATA
{
private int _ID { get; set; }
[XmlElement(ElementName = "ID")]
public string ID {
get { return _ID.ToString("D3");}
set{ _ID = int.Parse(value);}
}
[XmlElement(ElementName = "NAME")]
public string NAME { get; set; }
}
[XmlRoot(ElementName = "NewDataSet")]
public class CDataSet
{
[XmlElement(ElementName = "DATA")]
public DATA data { get; set; }
}
}
This is how my Xml should look after XML Serialization:
<value xsi:type="CD" otherAttributes= "IDK">
.
.
.
</value>
Thats my C# code to it:
public class Valué
{
[XmlAttribute(AttributeName ="xsi:type")]
public string Type { get; set; } = "CD";
[XmlAttribute(attributeName: "otherAttributes")]
public string OtherAttributes { get; set; } = "IDK"
}
Apparently the XmlSerializer can't serialize colons (:) in attributenames.... how do i fix this problem?
If i remove the colon from the attributeName itm works out fine ..
Do it the correct way :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
Valué value = new CD() { OtherAttributes = "IDK" };
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Valué));
serializer.Serialize(writer, value);
}
}
[XmlInclude(typeof(CD))]
public class Valué
{
}
public class CD : Valué
{
[XmlAttribute(attributeName: "otherAttributes")]
public string OtherAttributes { get; set; }
}
}
I have generated a c# schema using the xsd successfully and using that schema, input the data and generate an xml. for single dimensional arrays the data in input but it is not populated in the xml output.
c# schema generated using xsd (below is a piece of code from a big chunk of codes)
private CoreCorePathologyTypeTopographySNOMEDPathology[] topographySNOMEDPathologyField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("TopographySNOMEDPathology", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public CoreCorePathologyTypeTopographySNOMEDPathology[] TopographySNOMEDPathology
{
get
{
return this.topographySNOMEDPathologyField;
}
set
{
this.topographySNOMEDPathologyField = value;
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.datadictionary.nhs.uk/messages/COSDPathology-v8-1")]
public partial class CoreCorePathologyTypeTopographySNOMEDPathology : CV
{
}
The data to the above constructor is passed like this:
var TypesTopographySNOMEDPathology = new List<CoreCorePathologyTypeTopographySNOMEDPathology>();
var TopographySNOMEDPathology = new CoreCorePathologyTypeTopographySNOMEDPathology();
{
TopographySNOMEDPathology.code = ds.Tables[0].Rows[iRowCounter]["CORE_PATHOLOGY_TOPOGRAPHY_SNOMED_PATHOLOGY"].ToString();
}
TypesTopographySNOMEDPathology.Add(TopographySNOMEDPathology);
I expect the output as other data items like for example
<PathologyObservationReportId extension="4638661" />
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Data;
namespace ConsoleApplication122
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
ds.Tables.Add(dt);
dt.Columns.Add("CORE_PATHOLOGY_TOPOGRAPHY_SNOMED_PATHOLOGY", typeof(string));
dt.Rows.Add(new object[] { "6000"});
int iRowCounter = 0;
CoreCorePathologyTypeTopographySNOMEDPathology TopographySNOMEDPathology = new CoreCorePathologyTypeTopographySNOMEDPathology()
{
TopographySNOMEDPathology = new List<TopographySNOMEDPathology>() {
new TopographySNOMEDPathology() { code = (string)ds.Tables[0].Rows[iRowCounter]["CORE_PATHOLOGY_TOPOGRAPHY_SNOMED_PATHOLOGY"] }
}
};
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(CoreCorePathologyTypeTopographySNOMEDPathology));
serializer.Serialize(writer, TopographySNOMEDPathology);
}
}
[XmlRoot("CoreCorePathologyTypeTopographySNOMEDPathology")]
[XmlInclude(typeof(CV))]
public partial class CoreCorePathologyTypeTopographySNOMEDPathology : CV
{
[XmlElement("TopographySNOMEDPathology")]
public List<TopographySNOMEDPathology> TopographySNOMEDPathology { get; set; }
}
public class CV
{
}
[XmlRoot("TopographySNOMEDPathology")]
public class TopographySNOMEDPathology
{
public string code { get; set; }
}
}
I am having a problem with deserialization of an array which comes from the SOAP response. It returns null, but in response I can actually see a correct xml message. Maybe someone can see what's wrong in my code. Thanks in advance.
SOAP response:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns-wp="imcwp" xmlns:ns-hostax="imchostax" xmlns:ns-ilms="imcilms" xmlns:ns-qtms="imcqtms" xmlns:ns-tptms="imctptms">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns-wp:strTrailerRequest-TrailerResponse>
<ns-wp:Trailer>
<ns-wp:TrailerId>T001</ns-wp:TrailerId>
<ns-wp:TrailerType>Flat Extender</ns-wp:TrailerType>
</ns-wp:Trailer>
<ns-wp:Trailer>
<ns-wp:TrailerId>T002</ns-wp:TrailerId>
<ns-wp:TrailerType>Flat Extender</ns-wp:TrailerType>
</ns-wp:Trailer>
<ns-wp:Trailer>
<ns-wp:TrailerId>T003</ns-wp:TrailerId>
<ns-wp:TrailerType>Flat Extender</ns-wp:TrailerType>
</ns-wp:Trailer>
</ns-wp:strTrailerRequest-TrailerResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Response Model:
[XmlRoot(ElementName = "strTrailerRequest-TrailerResponse", Namespace = "imcwp")]
public class strTrailerRequestTrailerResponse
{
[XmlArray("strTrailerRequest-TrailerResponse", Namespace = "imcwp")]
[XmlArrayItem("Trailer", Namespace = "imcwp")]
public List<Trailer> Trailers { get; set; }
}
Parse Method:
private strTrailerRequestTrailerResponse ParseTrailerResponse(string response)
{
var soap = XDocument.Parse(response);
XNamespace ns = "imcwp";
var trailerResponseNode = soap.Descendants(ns + "strTrailerRequest-TrailerResponse").FirstOrDefault().ToString();
var result = Deserialize<strTrailerRequestTrailerResponse>(trailerResponseNode);
return result;
}
Why not just deserilize the whole object, in that case u dont need xDocument and querying:
var envelop = Deserialize<Envelope>(response);
foreach (var strTrailerRequestTrailerResponseTrailer in envelop.Body.strTrailerRequestTrailerResponse)
{
}
and yr Deserialize method:
public static T Deserialize<T>(string response)
{
var serializer = new XmlSerializer(typeof(T));
using(TextReader reader = new StringReader(response))
{
return (T)serializer.Deserialize(reader);
}
}
If you still want to go with yr way using XDocument, it's ok yr Deserialize method should the same as I defined. if you wont try:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "imcwp")]
public partial class strTrailerRequestTrailerResponseTrailer
{
public string TrailerId { get; set; }
public string TrailerType { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "imcwp")]
[System.Xml.Serialization.XmlRootAttribute("strTrailerRequest-TrailerResponse", Namespace = "imcwp", IsNullable = false)]
public partial class strTrailerRequestTrailerResponse
{
[System.Xml.Serialization.XmlElementAttribute("Trailer")]
public strTrailerRequestTrailerResponseTrailer[] Trailer { get; set; }
}
For simple xml you can use xml linq. See code below :
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace Certificate
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
XElement soap = doc.Root;
XNamespace ns = soap.GetNamespaceOfPrefix("ns-wp");
List<Trailer> trailers = doc.Descendants(ns + "Trailer").Select(x => new Trailer()
{
trailerId = (string)x.Element(ns + "TrailerId"),
trailerType = (string)x.Element(ns + "TrailerType")
}).ToList();
}
}
public class Trailer
{
public string trailerId { get; set; }
public string trailerType { get;set;}
}
}
I have two class : Osoba, test
public class test
{
public string raz { get; set; }
public string dwa { get; set; }
}
public class Osoba
{
public test tehe { get; set; }
}
I also add namespaces to main root and seralize
Osoba ne = new Osoba();
test t1 = new praca2.test();
t1.dwa = "fgfg";
t1.raz = "dfdfdfdf";
ne.tehe = t1;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
ns.Add("d", "http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields");
ns.Add("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
XmlSerializer xsSubmit = new XmlSerializer(typeof(Osoba));
var xml = #"D:\dupa1.xml";
using (var stream = new FileStream(xml, FileMode.Create))
{
using (XmlWriter writer = XmlWriter.Create(stream))
{
xsSubmit.Serialize(writer, ne,ns);
xml = stream.ToString(); // Your XML
}
}
I get
<?xml version="1.0" encoding="utf-8"?>
<Osoba xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls"xmlns:d="http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields">
<tehe>
<raz>dfdfdfdf</raz>
<dwa>fgfg</dwa>
</tehe>
</Osoba>
I want add to node namespaces examle:
...
<pc:tehe>
<dfs:raz>dfdfdfdf</dfs:raz>
<dfs:dwa>fgfg</dfs:dwa>
</pc:tehe>
How I can do it?
I try add class atribute which set namespace
[XmlRoot("Node", Namespace="http://flibble")]
but it bad idea
You're almost there you just need to modify your classes slightly:
public class test
{
[XmlElement(Namespace = "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution")]
public string raz { get; set; }
[XmlElement(Namespace = "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution")]
public string dwa { get; set; }
}
public class Osoba
{
[XmlElement(Namespace = "http://schemas.microsoft.com/office/infopath/2007/PartnerControls")]
public test tehe { get; set; }
}
Sample implementation copied mostly from yours:
class Program
{
static void Main(string[] args)
{
Osoba ne = new Osoba();
test t1 = new test();
t1.dwa = "fgfg";
t1.raz = "dfdfdfdf";
ne.tehe = t1;
XmlSerializer xsSubmit = new XmlSerializer(typeof(Osoba));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
ns.Add("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
var xml = #"D:\dupa1.xml";
using (var stream = new FileStream(xml, FileMode.Create))
{
using (XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8))
{
xsSubmit.Serialize(writer, ne, ns);
}
}
}
}
You will get this XML:
<?xml version="1.0" encoding="utf-8"?>
<Osoba xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
<pc:tehe>
<dfs:raz>dfdfdfdf</dfs:raz>
<dfs:dwa>fgfg</dfs:dwa>
</pc:tehe>
</Osoba>
Hth...
Uisng xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication42
{
class Program
{
static void Main(string[] args)
{
string xmlHeader =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<Osoba xmlns:dfs=\"http://schemas.microsoft.com/office/infopath/2003/dataFormSolution\"" +
" xmlns:pc=\"http://schemas.microsoft.com/office/infopath/2007/PartnerControls\"" +
" xmlns:d=\"http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields\">" +
"</Osoba>";
XDocument doc = XDocument.Parse(xmlHeader);
XElement osoba = doc.Root;
XNamespace dfsNs = osoba.GetNamespaceOfPrefix("dfs");
XNamespace pcNs = osoba.GetNamespaceOfPrefix("pc");
osoba.Add(new XElement(pcNs + "tehe", new object[] {
new XElement(dfsNs + "raz", "dfdfdfdf"),
new XElement(dfsNs + "dwa", "fgfg")
}));
}
}
}
I think you are new at C#.I suggest you to study C# basics, design patterns and repository pattern.For your requirement you can use below codes
public class Tehe
{
public string Raz { get; set; }
public string Dwa { get; set; }
}
public class TeheRepository
{
private System.Xml.Linq.XDocument xmlDatas;
public TeheRepository(string filePath)
{
xmlDatas = XDocument.Load(filePath);
}
public IEnumerable<Tehe> FindAll()
{
return xmlDatas.Elements().Elements().Select(tehe =>
{
Tehe t = new Tehe();
t.Dwa = tehe.Elements().ElementAt(1).Value;
t.Raz = tehe.Elements().ElementAt(0).Value;
return t;
});
}
}