I have one problem. I have to serialize an object and that sam object is converted to XML, but it's a datetime object.
Ok, i have string variable which is filled with data from some sql query, like this
//DateDeliveryRequest
if (rw_mat["dat_pot"].ToString().Length <= 0)
{
date_req = "";
}
else
{
date_req = rw_mat["dat_pot"].ToString();
}
Now, date_req is being passet to object like this:
var dtfi = new DateTimeFormatInfo { ShortDatePattern = "dd-MM-yyyy", DateSeparator = "-" };
Agr3PL.DataArea.Header.DateDeliveryRequest = Convert.ToDateTime(date_req, dtfi);
And at the end this object with among other is being passed to serialize function:
private string SerializeAnObject(object obj)
{
System.Xml.XmlDocument doc = new XmlDocument();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
System.IO.MemoryStream stream = new System.IO.MemoryStream();
try
{
serializer.Serialize(stream, obj);
stream.Position = 0;
doc.Load(stream);
return doc.InnerXml;
}
catch (Exception ex)
{
WriteErrors.WriteToLogFile("WS.SAVE_DOK_SERIJALIZACIJA", ex.ToString());
throw ex;
}
So i want to get datetime variable to xml but I don't, the xml has to look something like this(It is just a segment)
- <Header>
<MessageType>COR</MessageType>
<UniqueHeaderNumber />
<UniqueHeaderNumberFromWMS />
<CompanyCode />
<OrderNumber />
<InvoiceNumber />
<MovementNumber />
<ReceiptNumber />
<DebitNoteNumber />
<PickNoteNumber />
<LoadNumber />
<DropSequence />
<BulkPickNoteNumber />
<NumberOfPallets />
<DateDeliveryRequest />
But the problem is that the xml is not showing the node >DateDeliveryRequest it's not there
I don't get error just there is no node >DateDeliveryRequest???
I don't know is it the problem in serializer function or on something else, maybe in formating date or something else?
I tested this code:
public class Test
{
private DateTime dateDeliveryRequestField;
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime DateDeliveryRequest { get { return this.dateDeliveryRequestField; } set { this.dateDeliveryRequestField = value; } }
}
private string SerializeAnObject(object obj)
{
System.Xml.XmlDocument doc = new XmlDocument();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
System.IO.MemoryStream stream = new System.IO.MemoryStream();
try
{
serializer.Serialize(stream, obj);
stream.Position = 0;
doc.Load(stream);
return doc.InnerXml;
}
catch (Exception ex)
{
throw ex;
}
}
Test n = new Test();
n.DateDeliveryRequest = DateTime.Parse("2012-10-07");
string result = SerializeAnObject(n);
and result:
<?xml version="1.0"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DateDeliveryRequest>2012-10-07</DateDeliveryRequest>
</Test>
So everything looks good.
To serialize dates use this string format
date_req = rw_mat["dat_pot"].ToString("s");
Related
I am trying to create an application that imports an XML file into a TextBox, with the goal to edit the content.
After editing, the user should be able to save the content of the file, but at the same time to validate it. For example,
<Person id="22">
<Name gg="u">John</Name>
<Surname>Jones</Surname>
<PhoneNo>333333333111</PhoneNo>
<Country>Germany</Country>
</Person>
If the user edits the start tag "Name", but forgets to edits the end tag, it should throw an exception.
I have tried
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(MyTextBox.Text);
xmlDoc.Save(fileName);
and
XmlElement DocRoot = xmlDoc.CreateElement("root");
DocRoot.InnerText = MyTextBox.Text;
xmlDoc.AppendChild(DocRoot);
xmlDoc.Save(fileName);
None worked. I am grateful for any help, thank you!
I have though of this solution and it seems to work :) As per the xsd question, I have a generic XML.
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(MyTextBox.Text);
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true
};
XmlWriter writer = XmlWriter.Create(fileName, settings);
xmlDoc.Save(writer);
MessageBox.Show("File overwritten to: " + fileName);
}
catch (Exception ex)
{
MessageBox.Show("The textbox content is wrong. ");
}
Seems that you are trying to check if the XML text is well formed and not really if it is valid against a certain definition.
To check if the XML text is well formed, you can try to parse it and verify if it contains any errors. Here is a function that attempts to do that:
class Program
{
static void Main(string[] args)
{
var result = ValidateXml("<Person id=\"22\"><Name>John<Name></Person>");
if (!result.IsValid)
{
Console.WriteLine($"Line number: {result.Exception.LineNumber}");
Console.WriteLine($"Line position: {result.Exception.LinePosition}");
Console.WriteLine($"Message: {result.Exception.Message}");
}
// OUTPUT:
// Line number: 1
// Line position: 35
// Message: The 'Name' start tag on line 1 position 28 does not match the end tag of 'Person'.Line 1, position 35.
}
static ValidationResult ValidateXml(string xml)
{
using (var xr = XmlReader.Create( new StringReader(xml)))
{
try
{
while (xr.Read())
{
}
return ValidationResult.ValidResult;
}
catch (XmlException exception)
{
return new ValidationResult(exception);
}
}
}
public class ValidationResult
{
public static ValidationResult ValidResult = new ValidationResult();
private ValidationResult()
{
IsValid = true;
}
public ValidationResult(XmlException exception)
{
IsValid = false;
Exception = exception;
}
public bool IsValid { get; }
public XmlException Exception { get;}
}
}
I have a class that I deserialize with:
public static bool FileDeserializer<T>(string xmlFileName, out T element, out string strError)
{
try
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StreamReader(xmlFileName))
{ element = (T)xmlSerializer.Deserialize(reader); }
strError = string.Empty;
return true;
}
catch (Exception exc)
{
strError = "XmlFileDeserializer exception: " + exc;
element = default(T);
return false;
}
}
and serialize with
public static bool FileSerializer<T>(T value, string strFilename, out string strError)
{
try
{
var serializer = new XmlSerializer(typeof(T));
using (var xmlWriter = XmlWriter.Create(strFilename))
{ serializer.Serialize(xmlWriter, value); }
strError = string.Empty;
return true;
}
catch (Exception exc)
{
strError = "XmlFileSerializer exception: " + exc;
return false;
}
}
Now everything works fine with serialize/deserialize.
But when I try to read it to modify it:
with visual studio it's on a single line (so very hard to read)
with an other editor (xml explorer) i get the message:
The document does not have a specified schema. Click to apply one.
So I have searched for documentation but didn't understand how to put that in my code.
Thanks
---ADD---
Here is the xml in question sorry for not having added it before
<?xml version="1.0" encoding="utf-8"?><CfgData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><DialogFileIniDir>C:\temp</DialogFileIniDir><HorSplitterPos>204</HorSplitterPos><VerSplitterPos>358</VerSplitterPos><GridStep>10</GridStep><Scale>0</Scale><TraceThickness>3</TraceThickness><ShadowsEnabled>false</ShadowsEnabled><Theme>LIGHT</Theme><LightForeground><A>255</A><R>0</R><G>0</G><B>0</B><ScA>1</ScA><ScR>0</ScR><ScG>0</ScG><ScB>0</ScB></LightForeground><LightBackgound><A>255</A><R>245</R><G>245</G><B>245</B><ScA>1</ScA><ScR>0.913098633</ScR><ScG>0.913098633</ScG><ScB>0.913098633</ScB></LightBackgound><LightTraceOkColor><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></LightTraceOkColor><LightTraceCancelColor><A>255</A><R>255</R><G>0</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>0</ScG><ScB>1</ScB></LightTraceCancelColor><LightTraceEndColor><A>255</A><R>0</R><G>0</G><B>255</B><ScA>1</ScA><ScR>0</ScR><ScG>0</ScG><ScB>1</ScB></LightTraceEndColor><LightHeaderUnselectedBG><A>255</A><R>0</R><G>206</G><B>209</B><ScA>1</ScA><ScR>0</ScR><ScG>0.6172066</ScG><ScB>0.637596846</ScB></LightHeaderUnselectedBG><LightHeaderSelectedBG><A>255</A><R>0</R><G>0</G><B>255</B><ScA>1</ScA><ScR>0</ScR><ScG>0</ScG><ScB>1</ScB></LightHeaderSelectedBG><LightHeaderStartEndBG><A>255</A><R>105</R><G>105</G><B>105</B><ScA>1</ScA><ScR>0.141263291</ScR><ScG>0.141263291</ScG><ScB>0.141263291</ScB></LightHeaderStartEndBG><LightHeaderFG><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></LightHeaderFG><LightBlockBG><A>255</A><R>220</R><G>220</G><B>220</B><ScA>1</ScA><ScR>0.7156935</ScR><ScG>0.7156935</ScG><ScB>0.7156935</ScB></LightBlockBG><LightBlockFG><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></LightBlockFG><DarkForeground><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></DarkForeground><DarkBackgound><A>255</A><R>19</R><G>56</G><B>53</B><ScA>1</ScA><ScR>0.00651209056</ScR><ScG>0.0395462364</ScG><ScB>0.0356013142</ScB></DarkBackgound><DarkTraceOkColor><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></DarkTraceOkColor><DarkTraceCancelColor><A>255</A><R>255</R><G>0</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>0</ScG><ScB>1</ScB></DarkTraceCancelColor><DarkTraceEndColor><A>255</A><R>0</R><G>0</G><B>255</B><ScA>1</ScA><ScR>0</ScR><ScG>0</ScG><ScB>1</ScB></DarkTraceEndColor><DarkHeaderUnselectedBG><A>255</A><R>220</R><G>220</G><B>220</B><ScA>1</ScA><ScR>0.7156935</ScR><ScG>0.7156935</ScG><ScB>0.7156935</ScB></DarkHeaderUnselectedBG><DarkHeaderSelectedBG><A>255</A><R>0</R><G>0</G><B>255</B><ScA>1</ScA><ScR>0</ScR><ScG>0</ScG><ScB>1</ScB></DarkHeaderSelectedBG><DarkHeaderStartEndBG><A>255</A><R>105</R><G>105</G><B>105</B><ScA>1</ScA><ScR>0.141263291</ScR><ScG>0.141263291</ScG><ScB>0.141263291</ScB></DarkHeaderStartEndBG><DarkHeaderFG><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></DarkHeaderFG><DarkBlockBG><A>255</A><R>220</R><G>220</G><B>220</B><ScA>1</ScA><ScR>0.7156935</ScR><ScG>0.7156935</ScG><ScB>0.7156935</ScB></DarkBlockBG><DarkBlockFG><A>255</A><R>255</R><G>255</G><B>255</B><ScA>1</ScA><ScR>1</ScR><ScG>1</ScG><ScB>1</ScB></DarkBlockFG></CfgData>
so I'm a total noob to C# is there any way to make this work?
It would also be a great help if someone could explain why my system doesn't work, and why another version would.
using System;
using System.Xml;
public class XMLManager
{
private XmlTextReader reader;
private XmlDocument document;
private XmlNodeList nodeList;
public void OpenFile(string file)
{
try
{
reader = new XmlTextReader(file);
reader.WhitespaceHandling = WhitespaceHandling.None;
reader.MoveToContent();
document = new XmlDocument();
document.Load(reader);
nodeList = document.SelectNodes(#"Settings/Settings");
}
catch (System.IO.FileNotFoundException)
{
}
}
public void CloseFile()
{
if (reader != null)
{
((IDisposable)reader).Dispose();
reader.Close();
reader = null;
}
document = null;
nodeList = null;
}
public string Get(string attrib)
{
for (int i = 0; i < nodeList.Count; i++)
{
reader.MoveToAttribute(i);
if (reader.Name == attrib)
{
return reader.Value;
}
}
return null;
}
}
Edit: Sorry for my bad formatting, this is my first time posting on Stack Overflow.
You are making multiple mistakes here.
First of all, you don't need a reader to read xml content into an XmlDocument.
Second, while trying to get the attributes, you are trying to proceed to the attributes using the reader which is obviously not having the context of the selected nodes.
Here is your updated XmlManager, but I have to note, there is a logical error too, which is, when the GetAttribute is invoked, you are searching all the Settings/Settings nodes and if find the attribute in any of them, return it. If the xml file contains only one Settings/Settings node, SelectSingleNode is better. I assume the following format:
<Settings>
<Settings attr1="attr1val" attr2="attr2val" />
</Settings>
Note: I also removed CloseFile method because it is no longer required.
public class XMLManager
{
private XmlDocument document;
private XmlNodeList nodeList;
public void OpenFile(string file)
{
document = new XmlDocument();
document.Load(file);
nodeList = document.SelectNodes(#"Settings/Settings");
}
public string Get(string attrib)
{
for (int i = 0; i < nodeList.Count; i++)
{
if (nodeList[i].Attributes[attrib] != null)
{
return nodeList[i].Attributes[attrib].Value;
}
}
return null;
}
}
Overall, you're doing way too much work.
If you have XML in a file, load it directly into an XML (DOM) object using XmlDocument.Load( strFileName );
To iterate all nodes matching an XPath query, see how I run through them.
try {
string strFileName = HttpContext.Current.Server.MapPath("\\data.xml");
XmlDocument xml = new XmlDocument();
xml.Load( strFileName );
foreach (XmlElement ndRow in xml.SelectNodes("//row")) {
string strTemp = ndRow.GetAttribute("foo");
}
} catch (Exception ex) {
Response.Write(ex.Message);
}
explained.Getting exception when deserializing . Can anybody help me what has gone wrong for the reason. I have created a class for the data to be extracted from the xml file. But when deserialixing back to object I am getting exeption.
<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<n1:GetPlugStatusListResponse xmlns:n1="http://tempuri.org/SPSuiteWebService/StandService">
<n1:GetPlugStatusListResponse xmlns:n2="http://tempuri.org/GetPlugStatusListResponse.xsd">
<n2:StoreList>
<n2:Store>
<n2:AreaType>13</n2:AreaType>
<n2:AreaName>東京都</n2:AreaName>
<n2:StoreCd>91110002</n2:StoreCd>
</n2:Store>
<n2:Store>
</n2:Store>
...
</n2:StoreList>
public static List<Store> ParseStoreList(string fileName)
{
// Init
List<Store> listStoreList = new List<Store>();
// Parse...
using (XmlReader xmlReader = XmlReader.Create(fileName))
{
XmlSerializer EventSerializer = new XmlSerializer(typeof(Store));
while (xmlReader.ReadToFollowing("n2:Store"))
{
Store storeObject = (Store)EventSerializer.Deserialize(xmlReader.ReadSubtree());
listStoreList.Add(storeObject);
}
xmlReader.Close();
}
// Return value
return listStoreList;
}
public static List<PlugListData> ParsePlugList(string fileName)
{
// Init
List<PlugListData> listPlugList = new List<PlugListData>();
// Parse...
using (XmlReader xmlReader = XmlReader.Create(fileName))
{
XmlSerializer EventSerializer = new XmlSerializer(typeof(Store));
// Parse XML - "Event" nodes...
while (xmlReader.ReadToFollowing("n2:PlugStatus"))
{
PlugListData pluglistObject = (PlugListData)EventSerializer.Deserialize(xmlReader.ReadSubtree());
listPlugList.Add(pluglistObject);
}
// Cleanup...
xmlReader.Close();
}
// Return value
return listPlugList;
}
You could try the following
XmlSerializer deserializer = new XmlSerializer(typeof(Store));// create the serializer
TextReader reader = new StreamReader("n2:Store"); //read your text
object obj = deserializer.Deserialize(reader);// create object
Store xmlData = (Store)obj;// access data from object
I am loading MusicXML-files into my program. The problem: There are two “dialects”, timewise and partwise, which have different root-nodes (and a different structure):
<?xml version="1.0" encoding='UTF-8' standalone='no' ?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="2.0">
<work>...</work>
...
</score-partwise>
and
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE score-timewise PUBLIC "-//Recordare//DTD MusicXML 2.0 Timewise//EN" "http://www.musicxml.org/dtds/timewise.dtd">
<score-timewise version="2.0">
<work>...</work>
...
</score-timewise>
My code for deserializing the partwise score so far is:
using (var fileStream = new FileStream(openFileDialog.FileName, FileMode.Open))
{
var xmlSerializer = new XmlSerializer(typeof(ScorePartwise));
var result = (ScorePartwise)xmlSerializer.Deserialize(fileStream);
}
What would be the best way to differentiate between the two dialects?
Here's a way to do it by using an XDocument to parse the file, read the root element to determine the type, and read it into your serializer.
var xdoc = XDocument.Load(filePath);
Type type;
if (xdoc.Root.Name.LocalName == "score-partwise")
type = typeof(ScorePartwise);
else if (xdoc.Root.Name.LocalName == "score-timewise")
type = typeof(ScoreTimewise);
else
throw new Exception();
var xmlSerializer = new XmlSerializer(type);
var result = xmlSerializer.Deserialize(xdoc.CreateReader());
I would create both serializers
var partwiseSerializer = new XmlSerializer(typeof(ScorePartwise));
var timewiseSerializer = new XmlSerializer(typeof(ScoreTimewise));
Assuming that there is only these two I would call CanDeserialize method on one
using (var fileStream = new FileStream(openFileDialog.FileName, FileMode.Open))
{
using (var xmlReader = XmlReader.Create(filStream))
{
if (partwiseSerializer.CanDeserialize(xmlReader))
{
var result = partwiseSerializer.Deserialize(xmlReader);
}
else
{
var result = timewiseSerializer.Deserialize(xmlReader);
}
}
}
Obviously this is just an idea how to do it. If there were more options or according to your application design I would use a more sophisticated way to call CanDeserialize, but that method is the key in my opinion:
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.candeserialize.aspx
The XmlReader class can be found here:
http://msdn.microsoft.com/en-us/library/System.Xml.XmlReader(v=vs.110).aspx
If you're concerned about resource usage:
internal const string NodeStart = "<Error ";
public static bool IsErrorDocument(string xml)
{
int headerLen = 1;
if (xml.StartsWith(Constants.XMLHEADER_UTF8))
{
headerLen += Constants.XMLHEADER_UTF8.Length;
}
else if (xml.StartsWith(Constants.XMLHEADER_UTF16))
{
headerLen += Constants.XMLHEADER_UTF16.Length;
}
else
{
return false;
}
if (xml.Length < headerLen + NodeStart.Length)
{
return false;
}
return xml.Substring(headerLen, NodeStart.Length) == NodeStart;
}
internal class Constants
{
public const string XMLHEADER_UTF16 = "<?xml version=\"1.0\" encoding=\"utf-16\"?>";
public const string XMLHEADER_UTF8 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
}