I'm receiving text string messages, which should be XML-like.
However, sometimes that's not the case but I don't see what those messages look like:
Current code:
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
The Exception errormessage is quite elaborated (it mentions the wrong tags), but it does not mention the xml string itself:
Exception during data receiving event: [System.Xml.XmlException: Unexpected end of file has occurred. The following elements are not closed: ID, VM, HMS. Line 1, position 156.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ThrowUnclosedElements()
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at ... Information.FromString(String xml) in C:\...\Information.cs:line 40
at ....<ExtractInformation>d__71.MoveNext() in C:\...\Extraction.cs:line 161
at some_other_function(Byte[] data) in C:\...\Extraction.cs:line 134]
System.Xml.XmlException: Unexpected end of file has occurred. The following elements are not closed: ID, VM, HMS. Line 1, position 156.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ThrowUnclosedElements()
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at ... Information.FromString(String xml) in C:\...\Information.cs:line 40
at ....<ExtractInformation>d__71.MoveNext() in C:\...\Extraction.cs:line 161
at some_other_function(Byte[] data) in C:\...\Extraction.cs:line 134]
My idea was to add the xml-string to the Exception's Message property, but this seems to be read-only:
public static Information FromString(string xml)
{
var xmlDocument = new XmlDocument();
try
{
xmlDocument.LoadXml(xml);
}
catch (Exception ex)
{
ex.Message += "[" + xml + "]"; // <= compiler error CS0200
throw ex;
}
At that depth I don't have any logging possibilities and as I'm working with a server application, I can't show something on screen.
How can I add information to this Exception message (or to other properties/fields of the Exception)?
Related
In my unit testing project, I have merged all my xml files into single xml file and need to send to webservice to seperate it into modules.
So, I have used the below code in my webservice,
//xmlString is my xml file content
try
{
XElement XmlDocument = new XElement("XMLDocument");
XmlDocument testDoc = new XmlDocument();
testDoc.LoadXml(xmlString);
XmlDocument = XElement.Load(new XmlNodeReader(testDoc));
}
catch (Exception ex)
{
string returnString = ex.StackTrace.ToString();
returnString += "XML breaks the code";
return returnString;
}
EDIT: While running this in finalbuilder, I am getting below exception
Exception Message: at ModuleSeparator.GetDetails(String xmlString) System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
Results
Return value of 'ModuleSeparator' : at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at ModuleSeparator.GetDetails(String xmlString)XML breaks the code
Setting variable 'ModuleWiseTestCaseResults' to value ' at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at ModuleSeparator.GetDetails(String xmlString)XML breaks the code'.
My XML will look like,
<?xml version="1.0" encoding="utf-8"?>
<test-results name="Merged results" total="418" errors="0" failures="0" not-run="0" inconclusive="128" ignored="0" skipped="7" invalid="0" date="2016-03-08" time="10:47:33">
<test-suite type="Test Project" name="" executed="True" result="Skipped" success="True" time="311.143731" asserts="0">
<results></results>
</test-suite>
</test-results>
Our application needs to process XML files. Some times we receive XMLs with values as follows:
<DiagnosisStatement>
<StmtText>ST &</StmtText>
</DiagnosisStatement>
Because of &< my application is not able to load XML correctly and throwing exception as follows:
An error occurred while parsing EntityName. Line 92, position 24.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.Throw(String res)
at System.Xml.XmlTextReaderImpl.ParseEntityName()
at System.Xml.XmlTextReaderImpl.ParseEntityReference()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.Load(String filename)
at Transformation.GetEcgTransformer(String filePath, String fileType, String Manufacture, String Producer) in D:\Transformation.cs:line 160
Now I need to replace all occurrences of &< with 'and<' so that XML can get processed successfully without any exceptions.
This is what I did in order to load XML with the help of answer given by Botz3000.
string oldText = File.ReadAllText(filePath);
string newText = oldText.Replace("&<", "and<");
File.WriteAllText(filePath, newText, Encoding.UTF8);
xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
The Xml file is invalid, because & needs to be escaped as &, so you cannot just load the xml without getting an error. You can do it if you load the file as plain text though:
string invalid = File.ReadAllText(filename);
string valid = invalid.Replace("&<", "and<");
File.WriteAllText(filename, valid);
If you have control over how the Xml file is generated though, you should fix that issue by either escaping the & as & or by replacing it with "and" as you said.
In C# i'm trying to get the xml string from a big DataSet:
private string GetXmlFromDecomposedPortfolio(string dataSetName, DecomposedPortfolio ptf)
{
StringWriter writer = new StringWriter();
System.Data.DataSet ds = new System.Data.DataSet(dataSetName);
ds.Tables.Add(ptf.Security.Copy());
ds.WriteXml((TextWriter)writer, XmlWriteMode.IgnoreSchema);
return writer.ToString();
}
but i've got the exception:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.String.GetStringForStringBuilder(String value, Int32 startIndex, Int32 length, Int32 capacity)
at System.Text.StringBuilder.GetNewString(String currentString, Int32 requiredLength)
at System.Text.StringBuilder.Append(Char value) at System.IO.StringWriter.Write(Char value)
at System.Xml.XmlTextWriter.WriteStartElement(String prefix, String localName, String ns)
at System.Data.DataTextWriter.WriteStartElement(String prefix, String localName, String ns)
at System.Data.XmlDataTreeWriter.XmlDataRowWriter(DataRow row, String encodedTableName)
at System.Data.XmlDataTreeWriter.Save(XmlWriter xw, Boolean writeSchema)
at System.Data.DataSet.WriteXml(XmlWriter writer, XmlWriteMode mode)
at System.Data.DataSet.WriteXml(TextWriter writer, XmlWriteMode mode)
at Decompose.Library.Render.GetXmlFromDecomposedPortfolio(String dataSetName, DecomposedPortfolio ptf)
at Decompose.Library.Render.SavePE()
at Decompose.Library.WorkFlow.ProcessBatch()
Any suggestion?
First you create huge (apparently) xml data
ds.WriteXml((TextWriter)writer, XmlWriteMode.IgnoreSchema);
After clone it, into the string object writer.ToString();, so you almost double the memory you need.
What you can do, is to create XML row-per-row, so create kind of XmlDataSetRowEnumerator, that retrieves XML-per-row and yield returns the resulting XML.
I am having problems with deserializeation for an XML element, I am assuming it is something to do with the namespace in the XML element not being found by the deserializer.
The data is coming form an outside source, which I cannot modify as a string and I am using C# 4.0.
Any help, gratefully appreciated.
string xml = "<boolean xmlns=\"http://schemas.microsoft.com/2003/10/serialization/\">false</boolean>";
var xSerializer = new XmlSerializer(typeof(bool));
using (var sr = new StringReader(xml))
using (var xr = XmlReader.Create(sr))
{
var y = xSerializer.Deserialize(xr);
}
Error:
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=There is an error in XML document (1, 2).
Source=System.Xml
StackTrace:
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
...
...
...
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=<boolean xmlns='http://schemas.microsoft.com/2003/10/serialization/'> was not expected.
Source=System.Xml
StackTrace:
at System.Xml.Serialization.XmlSerializationPrimitiveReader.Read_boolean()
at System.Xml.Serialization.XmlSerializer.DeserializePrimitive(XmlReader xmlReader, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
InnerException:
It will work if you create your serializer as below
var xSerializer = new XmlSerializer(typeof(bool),null, null,
new XmlRootAttribute("boolean"),
"http://schemas.microsoft.com/2003/10/serialization/");
You can't use xml namespaces and attributes if you want to deserialize a boolean. Infact you have to deserialize this:
string xml = "<boolean>false</boolean>";
I am running the exact same code in a WP7 application and a C# 3.5 application. The WP7 application throws a NotSupportedException upon calling XDocument.Parse() while the C# 3.5 application parses the XML with no problems. Below is the code used:
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(DownloadThreadsComplete);
client.DownloadStringAsync(new Uri("http://us.battle.net/sc2/en/forum/40568/", UriKind.Absolute));
...
private static void DownloadThreadsComplete(object sender, DownloadStringCompletedEventArgs e)
{
var doc = XDocument.Parse(e.Result);
}
Any idea why this is happening? It's strange that it is failing when trying to parse an SC2 forum when a WoW forum works just fine (http://us.battle.net/wow/en/forum/984270/).
Edit:
The exception message is "NotSupportedException". Here's the full stack trace:
at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options)
at System.Xml.Linq.XDocument.Parse(String text)
at SC2ForumReader.Pages.ForumViewerPage.DownloadThreadsComplete(Object sender, DownloadStringCompletedEventArgs e)
at System.Net.WebClient.OnDownloadStringCompleted(DownloadStringCompletedEventArgs e)
at System.Net.WebClient.DownloadStringOperationCompleted(Object arg)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at System.Delegate.DynamicInvokeOne(Object[] args)
at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
at System.Delegate.DynamicInvoke(Object[] args)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)
Edit2:
I've done what was suggested and have looked at the output of the 2 different requests. Additionally in my 3.5 client application I forced the user-agent to be the same as it is in the WP7 emulator to ensure it's not the user-agent causing the issue.
Here's the doctype declaration copied from Visual Studio:
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">
The doctypes are the same in each document but there are a few discrepancies in the files that stand out (it looks like there are a few extra characters inserted on the 3.5 side):
WP7 Emulator: StarCraft II
3.5 Application: StarCraft II
The problem is that XDocument.Parse enables DTD processing (which is normally disabled by default on a XmlTextReader) yet it does not supply a resolver. Try this code instead:
private static void DownloadThreadsComplete(object sender, DownloadStringCompletedEventArgs e)
{
XDocument doc;
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
using (XmlReader reader = XmlReader.Create(new StringReader(e.Result), settings))
{
doc = XDocument.Load(reader);
}
// Do stuff with doc
}
OR:-
private static void DownloadThreadsComplete(object sender, DownloadStringCompletedEventArgs e)
{
XDocument doc;
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = new XmlPreloadedResolver(XmlKnownDtds.Xhtml10);
using (XmlReader reader = XmlReader.Create(new StringReader(e.Result), settings))
{
doc = XDocument.Load(reader);
}
// Do stuff with doc
}