The company receives a form of XML files and stores them on an S3 bucket, the information is then shown on a customers website.
Issue I am having is they have onboarded a new customer with a new feed. The customers feed which they are now sending me are correct, Although their XML files are missing the declaration at the top.
Example of Declaration missing
<?xml version="1.0" encoding="UTF-8"?>
This is stopping the feed from processing and displaying on the website.
If I manually add the Declaration and re upload it works.
Now the customer is saying they have never had the headers and it works for other 3rd party companies.
Is there a way to add the header once receiving the files, the feed processor & FTP server are in c#, dotnet3.1
public static T Deserialize<T>(XmlReader reader)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Parse;
// using (StringReader stringReader = new StringReader(objectXml))
// using (var xmlReader = XmlReader.Create(stringReader, settings))
{
retVal = serializer.Deserialize(reader);
return (T)retVal;
}
}
public static T Deserialize<T>(XDocument xdoc)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Parse;
using (StringReader stringReader = new StringReader(xdoc.ToString()))
using (var xmlReader = XmlReader.Create(stringReader, settings))
{
retVal = serializer.Deserialize(xmlReader);
return (T)retVal;
}
}
public static T Deserialize<T>(string objectXml)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Parse;
using (StringReader stringReader = new StringReader(objectXml))
using (var xmlReader = XmlReader.Create(stringReader, settings))
{
retVal = serializer.Deserialize(xmlReader);
return (T)retVal;
}
}
// public static T Deserialize<T>(string objectXml, string xmlNamespace)
// {
// var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", xmlNamespace) });
// object retVal = null;
// XmlSerializer serializer = new XmlSerializer(typeof(T));
// var settings = new XmlReaderSettings();
// settings.IgnoreComments = true;
// settings.ConformanceLevel = ConformanceLevel.Document;
// settings.DtdProcessing = DtdProcessing.Parse;
// using (StringReader stringReader = new StringReader(objectXml))
// using (var xmlReader = XmlReader.Create(stringReader, settings))
// {
// retVal = serializer.Deserialize(xmlReader);
// return (T)retVal;
// }
// }
public static T Deserialize<T>(Stream xmlStream)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty, new XmlQualifiedName("xs", "http://www.w3.org/2001/XMLSchema") });
object retVal = null;
XmlSerializer serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Document;
settings.DtdProcessing = DtdProcessing.Ignore;
using (var xmlReader = XmlReader.Create(xmlStream, settings))
{
retVal = serializer.Deserialize(xmlReader);
return (T)retVal;
}
}
}
}
public static class XmlUtil
{
public static string SerializeToString<T>(T value)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = false;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
// This adds our DocType
writer.WriteDocType("propertyList", null, "http://reaxml.realestate.com.au/propertyList.dtd", null);
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
public static string SerializeToStringUTF8<T>(T value)
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.Encoding = Encoding.UTF8;
settings.OmitXmlDeclaration = false;
using (var stream = new StringWriterWithEncoding(Encoding.UTF8))
using (var writer = XmlWriter.Create(stream, settings))
{
// This adds our DocType
writer.WriteDocType("propertyList", null, "http://reaxml.realestate.com.au/propertyList.dtd", null);
serializer.Serialize(writer, value, emptyNamespaces);
return stream.ToString();
}
}
Related
I have a DeepClone function using Newtonsoft:
public static T DeepClone2<T>(this T obj)
{
var jsonSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.All
};
var stringBuilder = new StringBuilder();
var stringWriter = new StringWriter(stringBuilder);
using (JsonWriter writer = new JsonTextWriter(stringWriter))
{
writer.Formatting = Formatting.None;
var serializer = JsonSerializer.Create(jsonSettings);
serializer.Serialize(writer, obj);
writer.Flush();
}
string objSerialized = stringBuilder.ToString();
T clonedObj = JsonConvert.DeserializeObject<T>(objSerialized, jsonSettings);
return clonedObj;
}
This function is exploding the stack memory when the object has a loop.
However, if I configure the ReferenceLoopHandling to Error, then it gives an error.
Why isn't the loop ignored?
I'm trying to get this:
<ATCWaypointEnd id="KLKP">
</ATCWaypointEnd>
But i get this:
<ATCWaypointEnd id="KLKP"></ATCWaypointEnd>
Here is my Code:
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteStartAttribute("id");
writer.WriteString(ICAO);
writer.WriteFullEndElement();
I would recommend creating a class to represent your XML file and then use serialization. That way you can let the framework create the XML elements and you can easily specify whether it should contain line breaks or not (indentation).
You can also use an external tool to generate your POCO classes, for example: https://xmltocsharp.azurewebsites.net/
Using the piece of xml you provided:
// The class representing the XML file
[XmlRoot(ElementName="ATCWaypointEnd")]
public class ATCWaypointEnd
{
[XmlAttribute(AttributeName="id")]
public string Id { get; set; }
}
// The method that will return the object as a XML string
public static string GenerateXml(ATCWaypointEnd obj)
{
string xml;
using (var stream = new MemoryStream())
{
var serializer = new XmlSerializer(typeof(ATCWaypointEnd));
var writer = new XmlTextWriter(stream, encoding);
writer.Formatting = Formatting.Indented; // Here
serializer.Serialize(writer, obj);
xml = encoding.GetString(stream.ToArray());
}
return xml;
}
And then in your code you can use like this:
var obj = new ATCWaypointEnd();
obj.Id = "KLKP";
var xml = GenerateXml(obj);
You can do the following:
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteAttributeString("id", ICAO);
writer.WriteString(System.Environment.NewLine);
writer.WriteFullEndElement();
See below for full code:
Add the following "using" statements:
using System.Xml;
using System.IO;
Option 1:
private void WriteXmlData(string ICAO, string filename)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = false;
settings.NewLineChars = Environment.NewLine;
string dirName = System.IO.Path.GetDirectoryName(filename);
if (!System.IO.Directory.Exists(dirName))
{
System.Diagnostics.Debug.WriteLine("Output folder doesn't exist. Creating.");
//create folder if it doesn't exist
System.IO.Directory.CreateDirectory(dirName);
}
using (XmlWriter writer = XmlWriter.Create(filename, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteAttributeString("id", ICAO);
writer.WriteString(System.Environment.NewLine);
writer.WriteFullEndElement();
writer.WriteEndDocument();
writer.Close();
writer.Dispose();
}
}
Usage:
WriteXmlData("KLKP", #"C:\Temp\test.xml");
Option 2:
private string WriteXmlData(string ICAO)
{
string xmlOutput = string.Empty;
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = false;
settings.NewLineChars = Environment.NewLine;
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("ATCWaypointEnd");
writer.WriteAttributeString("id", ICAO);
writer.WriteString(System.Environment.NewLine);
writer.WriteFullEndElement();
writer.WriteEndDocument();
writer.Close();
writer.Dispose();
}
//reset position
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
//put XML into string
xmlOutput = sr.ReadToEnd();
//clean up
sr.Close();
sr.Dispose();
}
//clean up
ms.Close();
ms.Dispose();
}
return xmlOutput;
}
Usage:
string output = WriteXmlData("KLKP");
I'm trying to serialize objects to XML. I'm having an issue that xsi and xsd are being added by default. I added the following code to remove the namespaces:
public string CommitDocumentToRepository(string extension, byte[] fileBytes)
{
//Convert to PDF
byte[] loPDFFileBytes;
ConversionService.ContentResponse loResponse = new DocumentAdapter.ConversionService.ContentResponse();
using (ConversionService.CustomPDFSoapClient loConversionServiceClient = new DocumentAdapter.ConversionService.CustomPDFSoapClient())
{
loResponse = loConversionServiceClient.OfficeToPDFContent(fileBytes, extension);
loPDFFileBytes = loResponse.ContentPDF;
}
if (loPDFFileBytes != null)
{
xform loDocContainer = new xform();
xformInstance loDocProperties = new xformInstance();
loDocProperties.FIRST_NAME= this.FirstName;
loDocProperties.LAST_NAME= this.LastName;
loDocProperties.MID_NAME = this.MidName;
loDocContainer.instance = loDocProperties;
string lsTempFile = System.IO.Path.GetTempFileName();
string lsXMLofProperties = loDocContainer.Serialize();
XmlDocument loDoc = new XmlDocument();
loDoc.LoadXml(lsXMLofProperties);
loDoc.Save(lsTempFile);
byte[] loFilePropertiesXML = Common.StreamFile(lsTempFile);
string lsReturnValue = string.Empty;
try
{
using (ISCommittalService.CommittalSoapClient loCommittalServiceClient = new DocumentAdapter.ISCommittalService.CommittalSoapClient())
{
lsReturnValue = loCommittalServiceClient.CommitDocumentByte(loPDFFileBytes, ".PDF", loFilePropertiesXML);
}
}
catch (Exception loException)
{
ADConnectionException loConnectionException = new ADConnectionException(loException);
throw loException;
}
return lsReturnValue;
}
else
return string.Empty;
}
public string Serialize()
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8;
StringBuilder loBuilder = new StringBuilder();
XmlSerializer formatter = new XmlSerializer(this.GetType());
using (StringWriter loWriter = new StringWriter(loBuilder))
{
formatter.Serialize(loWriter, this,ns);
}
return loBuilder.ToString();
}
This is the output:
<?xml version="1.0" encoding="UTF-16"?>
<xform>
<instance>
<FIRST_NAME xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q4:string"
xmlns:q4="http://www.w3.org/2001/XMLSchema">John</FIRST_NAME>
<MID_NAME xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q3:string" xmlns:q3="http://www.w3.org/2001/XMLSchema"/>
<LAST_NAME xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q5:string"
xmlns:q5="http://www.w3.org/2001/XMLSchema">Doe</LAST_NAME>
</instance>
</xform>
How can I remove that added xmlns (xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance"
d3p1:type="q4:string"
xmlns:q4="http://www.w3.org/2001/XMLSchema") from each object?
and how can I change it to utf-8 because xws.Encoding = Encoding.UTF8; that is my code seems doesn't have any affect.
Microsoft recommend to use XmlWriter instead of XmlTextWriter
https://msdn.microsoft.com/en-us/library/system.xml.xmltextwriter(v=vs.110).aspx
public string Serialize(BackgroundJobInfo info)
{
var stringBuilder = new StringBuilder();
using (var stringWriter = new StringWriter(stringBuilder, CultureInfo.InvariantCulture))
{
var writer = new XmlTextWriter(stringWriter);
new DataContractSerializer(typeof(BackgroundJobInfo)).WriteObject(writer, info);
}
return stringBuilder.ToString();
}
How to correctly use XmlWriter in my method instead of XmlTextWriter?
I'd use the factory method Create on XmlWriter class like:
var stringBuilder = new StringBuilder();
using(var writer = XmlWriter.Create(stringBuilder))
{
new DataContractSerializer(typeof(BackgroundJobInfo)).WriteObject(writer, info)
}
Or you can do it without XmlWriter
public static string Serialize(BackgroundJobInfo info)
{
string result = String.Empty;
using (var ms = new MemoryStream())
{
var sw = new StreamWriter(ms);
DataContractSerializer dcs = new DataContractSerializer(typeof(BackgroundJobInfo));
dcs.WriteObject(ms, info);
sw.Flush();
ms.Position = 0;
var sr = new StreamReader(ms);
result = sr.ReadToEnd();
}
return result;
}
I encountered a problem with SOAP serialization and it would be great to find an answer. Here's a very simplified example:
public void Test()
{
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
serializer.Serialize(writer, new A());
}
[Serializable]
public class A
{
public A()
{
BB = new B();
}
public int a;
public B BB;
}
[Serializable]
public class B
{
public int A1 { get; set; }
public int A2 { get; set; }
}
If I run method Test() then I get the following exception: System.InvalidOperationException: Token StartElement in state Epilog would result in an invalid XML document.
Would appreciate any help.
Use XmlWriter instead of StringWriter and do a writer.WriteStartElement("root");
This will work:
Stream s = new MemoryStream();
XmlWriter writer = new XmlTextWriter(s, Encoding.UTF8);
SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
writer.WriteStartElement("root");
serializer.Serialize(writer, new A());
StreamReader sr = new StreamReader(s);
string data = sr.ReadToEnd();
Just a note,
The upper example will not work if the position of the stream is not set to the start of the stream. Like so:
Stream s = new MemoryStream();
XmlWriter writer = new XmlTextWriter(s, Encoding.UTF8);
SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
writer.WriteStartElement("root");
serializer.Serialize(writer, new A());
s.Position = 0;
StreamReader sr = new StreamReader(s);
string data = sr.ReadToEnd();