System.Xml.XmlException in C# [duplicate] - c#

This question already has an answer here:
Reading xml file causes HRESULT: 0xC00CE556 [duplicate]
(1 answer)
Closed 6 years ago.
I'm trying to load ";" in a Xml document to my form at the code worked fine until yesterday when I got the error message below for some reson, I haden't made any changes to the code.
Error:
"An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll
Additional information: Data at the root level is invalid. Line 1, position 1."
The Code:
XmlDocument myContacts = new XmlDocument();
string path = "C:\\Users\\Name\\\mycontacts.xml";
private void LoadContacts()
{
myContacts.LoadXml(path);
foreach (XmlNode node in myContacts.SelectNodes("Contacts/Contact"))
{
lstContacts.Items.Add(node.SelectSingleNode("Name").InnerText);
}
}
I've tried Linq (XDocument) to but get the same problem there but at ";" in the Program.cs Main.
Application.Run(new Form1());
I've googled around and tried James Schubert's solution with no result.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<Contacts>
<Contact>
<Name>Testing</Name>
<Email>test#gmail.com</Email>
<Phone>070 00 00 000</Phone>
<Street>Test A1</Street>
<Zip>000 00</Zip>
<Town>Testing</Town>
</Contact>
</Contacts>
I know there's lots of threads on the topic already but can't get any of their answers/solutions to work.
Is there any more "magic" ways to deal with this problem than the ones I've been able to find when searching for solutions?

XmlDocument.LoadXml is for parsing an XML string. An example from the docs:
XmlDocument doc = new XmlDocument();
doc.LoadXml("<item><name>wrench</name></item>");
To load from a file, use XmlDocument.Load.
As an aside, I'd suggest you look at LINQ to XML if you haven't already. It's a much nicer API.

Related

Insert a node into a XML file

I am trying to add a single line/node (provided below) into an XML:
<Import Project=".www\temp.proj" Condition="Exists('.www\temp.proj')" />
The line could be under the main/root node of the XML:
<Project Sdk="Microsoft.NET.Sdk">
The approach I used:
XmlDocument Proj = new XmlDocument();
Proj.LoadXml(file);
XmlElement root = Proj.DocumentElement;
// Not sure about the next steps
root.SetAttribute("not sure", "not sure", "not sure");
Though I don't exactly know how to add that line in the XML, cause it was my first try on directly editing XML files, the error caused an extra problem over it.
I get this error on my first attempt:
C# "loadxml" 'Data at the root level is invalid. Line 1, position 1.'
Know this error was a famous one, which some provided a variety of approaches in this link:
xml.LoadData - Data at the root level is invalid. Line 1, position 1
Unfortunately, most of the solutions are outdated, the answer didn't work on this case, and I don't know how to apply others on this case.
Provided/accepted answer on the link for that issue:
string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))
{
xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}
Basically it didn't work, cause xml.StartsWith seems not existing anymore, at the same time xml.Remove also doesn't exist.
Can you please provide a piece of code that bypass the error and add the line to the XML?
Edit:
The sample XML file is provided in the comments section.
For the Xml posted in the comment, I have used two approachs :
1 - XmlDocument
XmlDocument Proj = new XmlDocument();
Proj.Load(file);
XmlElement root = Proj.DocumentElement;
//Create node
XmlNode node = Proj.CreateNode(XmlNodeType.Element, "Import", null);
//create attributes
XmlAttribute attrP = Proj.CreateAttribute("Project");
attrP.Value = ".www\\temp.proj";
XmlAttribute attrC = Proj.CreateAttribute("Condition");
attrC.Value = "Exists('.www\\temp.proj')";
node.Attributes.Append(attrP);
node.Attributes.Append(attrC);
//Get node PropertyGroup, the new node will be inserted before it
XmlNode pG = Proj.SelectSingleNode("/Project/PropertyGroup");
root.InsertBefore(node, pG);
Console.WriteLine(root.OuterXml);
2 - Linq To Xml, by using XDocument
XDocument xDocument = XDocument.Load(file);
xDocument.Root.AddFirst(new XElement("Import",
new XAttribute[]
{
new XAttribute("Project", ".www\\temp.proj"),
new XAttribute("Condition", "Exists('.www\\temp.proj')")
}));
Console.WriteLine(xDocument);
Namespace to add for XDocument:
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
Both solutions give the same result, but the last one is simple.
I hope you find this helpful.
Would it be possible for you to use the official MSBuild libraries?(https://www.nuget.org/packages/Microsoft.Build/)
I'm not sure which nuget package is actually required to read and edit project files only.
I've tried to programatically edit MSBuild project files directly and can not recommend it. It broke regulary due to unexpected changes...
The MSBuild library does a good job in editing project files and e.g. adding Properties, Items or Imports.

Deserialize an xml file or parse using linq to xml

Simplified XML file I need to decode:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:deliverylistResponse xmlns:ns2="http://tdriverap3.wsbeans.iseries/">
<return>
<COUNT>3</COUNT>
<DELIVERIES>
<ADD1>1300 address 1</ADD1>
<CITY>NICE CITY</CITY>
<ZIP>85705</ZIP>
</DELIVERIES>
<DELIVERIES>
<ADD1>40 S PINAL PKWY AVE</ADD1>
<CITY>FLORENCE</CITY>
<ZIP>85132</ZIP>
</DELIVERIES>
<DELIVERIES>
<ADD1>1825 EAST MAIN</ADD1>
<CITY>CHANDLER</CITY>
<ZIP>85286</ZIP>
</DELIVERIES>
<ERRORCODE/>
<RUNDATE>09/26/2018</RUNDATE>
</return>
</ns2:deliverylistResponse>
</soap:Body>
</soap:Envelope>
I am using the following to try and decode each of the individual addresses in the code.
I cannot figure out how to access them.
XElement xelement = XElement.Load(#"e:\test\X2.xml");
IEnumerable<XElement> addresses = xelement.Elements();
foreach (var address in addresses)
{
Console.WriteLine(address);
Console.WriteLine(address.Element("CITY").Value);
}
The first writeline works (it outputs the entire XML tree), the second says "System.Xml.Linq.XContainer.Element(...) returned null" - I have tried using DELIVERIES, COUNT, Body etc...
Obviously I am not telling it correctly how to traverse the structure, but I do not know how to go any further with it..
UPDATE: Thanks to some help I have figured out how to do it using Linq.
I would still like to be able to deserialize it if anybody has a pointer.
I followed several tutorials, but the multiple levels of this XML seems to be throwing me off.
I have created a class to hold the data but that is as far as my success with that path has gone.
Thank you,
Joe
Thank you Crowcoder -- this is what I wound up with, which will work.
The real XML file however does have about 60 fields so this is not as good as using a deserialize routine but I can at least move forward with the project.
XElement xelement = XElement.Load(#"e:\test\x2.xml");
IEnumerable<XElement> textSegs =
from seg in xelement.Descendants("DELIVERIES")
select seg;
foreach (var address in textSegs)
{
Console.WriteLine(address.Element("ADD1").Value);
Console.WriteLine(address.Element("CITY").Value);
Console.WriteLine(address.Element("ZIP").Value);
}
Console.ReadKey();

Asternet AGI GeneralMappingStrategy using XML

I am trying to use XML for my GeneralMappingStrategy in Asternet. I have my program working fine using List
such as:
agiServer.MappingStrategy = new GeneralMappingStrategy(
new List<ScriptMapping>()
{
new ScriptMapping() {
ScriptName = "testIVR",
ScriptClass = "Asterisk_Test.testIVR",
}
});
But I'd rather have it read an XML file as it says it can do in the documentation, however it does not seem to say anywhere what the XML format is required.
I have tried:
string pathtoxml = "test.xml";
agiServer.MappingStrategy = new GeneralMappingStrategy(pathtoxml);
With my XML as:
<?xml version="1.0"?>
<ScriptMapping>
<ScriptName>testIVR</ScriptName>
<ScriptClass>Asterisk_Test.testIVR</ScriptClass>
</ScriptMapping>
As a complete guess, seemed to make sense, but this won't compile, I get errors of:
System.InvalidOperationException: 'There was an error reflecting type 'System.Collections.Generic.List`1[AsterNET.FastAGI.MappingStrategies.ScriptMapping]'.'
Does anyone happen to know how to do this?
It appears that there was an issue with the Aster.NET library, I've now submitted the fix and it's been accepted. For anyone who has an issue on this in the future, the XML format is:
<?xml version="1.0"?>
<ArrayOfScriptMapping xmlns:xsi="w3.org/2001/XMLSchema-instance"; xmlns:xsd="w3.org/2001/XMLSchema">
<ScriptMapping>
<ScriptName>testIVR</ScriptName>
<ScriptClass>Asterisk_newTest.testIVR</ScriptClass>
</ScriptMapping>
</ArrayOfScriptMapping>

Parsing XFDL Contents - C#

I am tasked with ripping and stripping pertinent data from XFDL files. I am attempting to use XmlDocument's SelectSignleNode method to do so. However, it has proven unsuccessful.
Represntative XML:
<XFDL>
...
<page1>
<check3>true</check3>
</page1>
...
<page sid="PAGE1">
<check sid="CHECK9">
<value>true</value>
</check>
</page>
...
Code:
XmlDocument document = new XmlDocument();
document.Load(memoryStream);//decoded and unzipped xfdl file
//Doesn't work
XmlNode checkBox = document.SelectSingleNode("//check[#sid='CHECK9']/value");
//Doesn't work
XmlNode checkBox = document.SelectSingleNode("//page[#sid='PAGE1']/check[#sid='CHECK9']");
MsgBox(checkBox.InnerXml);
Yields me System.NullReferenceException as an XmlNode isn't selected.
I think I'm having an xpath issue but I can't seem to understand where. The earlier xml node is easily selected using:
XmlNode checkBox = document.SelectSingleNode("//page1/check3");
MsgBox(checkBox.InnerText);
Displays just fine. And just to head it off at the pass, there isn't a definition of <check9></check9> in the <page1> tag.
Anyone have some insight?
Thanks in advance.
Okay, so here's the deal. XFDL defines a default namespace that requires an arbitrary mapping for xpath querying. In my case:
XML:
<XFDL xmlns="http://www.ibm.com/xmlns/prod/xfdl/8.0" ... >
Code:
manager.AddNamespace("a", "http://www.ibm.com/xmlns/prod/xfdl/8.0");
//Append 'a:' to query elements
document.SelectSingleNode("//a:check[#sid='CHECK9']/a:value", manager);
The problem is compounded because <check> is buried in <page> which is defined in another namespace: xfdl. My xpath query becomes:
document.SelectSingleNode("//xfdl:page[#sid='PAGE1']/a:check[#sid='CHECK9']/a:value", manager);
Now this is rather XFDL specific but can be applied to other issues where there are multiple namespaces defined within an XML document.
EDIT 1
Source: http://codeclimber.net.nz/archive/2008/01/09/How-to-query-a-XPath-doc-that-has-a-default.aspx

Reading XML with unclosed tags in C#

I have a program which runs tests and generates a grid-view with all the results in it, and also an XML log file. The program also has the functionality to load logs to replicate the grid-view.
Since the program writes to the log file as its executing, if it crashes the log file will be missing closing tags. I still want to be able to load these XML files though as there is still lots of valuable data that can help me find out what caused the crash.
I was thinking maybe going through the XML file and closing off any unclosed XML tag, or maybe writing some kind of "Dirty" XML reader that would pretend every tag was closed. Any ideas on what I could do or how I should proceed?
Edit:
<Root>
<Parent>
<Child Name="One">
<Foo>...</Foo>
<Bar>...</Bar>
<Baz>...</Baz>
</Child>
<Child Name="Two">
<Foo>...</Foo>
<Bar>...</Bar>
!-- Crash happens here --!
From this I would still look to produce
Child Foo Bar Baz
One ... ... ...
Two ... ... /
Presumably it's all valid until it's truncated... so using XmlReader could work... just be prepared to handle it going bang when it reaches the truncation point.
Now the XmlReader API isn't terribly pleasant (IMO) so you might want to move to the start of some interesting data (which would have to be complete in itself) and then call the XNode.ReadFrom(XmlReader) method to get that data in a simple-to-use form. Then move to the start of the next element and do the same, etc.
Sample code:
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
using (XmlReader reader = XmlReader.Create("test.xml"))
{
while (true)
{
while (reader.NodeType != XmlNodeType.Element ||
reader.LocalName != "Child")
{
if (!reader.Read())
{
Console.WriteLine("Finished!");
}
}
XElement element = (XElement) XNode.ReadFrom(reader);
Console.WriteLine("Got child: {0}", element.Value);
}
}
}
}
Sample XML:
<Root>
<Parent>
<Child>First child</Child>
<Child>Second child</Child>
<Child>Broken
Sample output:
Got child: First child
Got child: Second child
Unhandled Exception: System.Xml.XmlException: Unexpected end of file has occurred
The following elements are not closed: Child, Parent, Root. Line 5, position 18.
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r)
at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r, LoadOptions o)
at System.Xml.Linq.XElement.ReadElementFrom(XmlReader r, LoadOptions o)
at System.Xml.Linq.XNode.ReadFrom(XmlReader reader)
at Program.Main(String[] args)
So obviously you'd want to catch the exception, but you can see that it managed to read the first two elements correctly.
As a last resort and depending on what you're doing, you could use an HTML reader like HtmlAgilityPack(Nuget page) or SGMLReader. SGMLReader will actually convert it to an XmlDocument, so that might be more what you're looking for.
Of course, HTML isn't XML so you get what you get when using this method.
There is no such thing in the Framework taht does this by default, neither is there a good solution available that will somehow parse generic invalid xml.
The most sensable thing yu can do is fixing the XML before starting to read it. Since only the end is cut off you should be able to figure out all open tags and close them.

Categories

Resources