XDocument Exception: Root element is missing - c#

I have a simple XML file:
<?xml version="1.0" encoding="utf-8" ?>
<Config>
<NumOfBytesInRow>20</NumOfBytesInRow>
<FirstBaudRate>115200</FirstBaudRate>
<SecondBaudRate>34800</SecondBaudRate>
<DefaultPort>COM1</DefaultPort>
<NumOfTries>2</NumOfTries>
</Config>
And I'm trying to get the elements, but as soon as I'm opening the file I'm getting an exception that the root element is missing
XDocument doc = new XmlDocument();
doc.Load(path);
EDIT
I have added:
if(File.Exists("D:\\BBConfig.xml"))
before the load it found the file and still same error

For the first I find the answer of user3890766 very good: "This exception could be thrown if the method can't find the file". But nevertheless you can try this for sure:
string strXml;
try
{
using (StreamReader sr = new StreamReader("myXML.xml"))
{
strXml = sr.ReadToEnd();
}
XmlDocument doc = new XmlDocument();
doc.LoadXml(strXml);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

This exception could be thrown if the method can't find the file. You need to check if your application can find the file at the given path, and have the authorization to read it.
To be sure, you could use a Stream, and check the Length. Then use XmlDocument.Load with this Stream.

Related

Parsing wrongly formatted XML-SOAP with C#

I have malformed XML (SOAP) file which I need to parse. The issue is that XML doesn't have proper header tags.
I've tried to parse file with XDocument and XmlDocument but neither has worked. XML starts from the line 30, so maybe there is some way to skip those lines before file is read by XML parser?
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd">
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="Finvoice.xsl"?>
<GGVersion="2.01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="a.xsd">
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader r = XmlReader.Create(file.FullName, settings);
XmlDocument xDoc = new XmlDocument();
xDoc.PreserveWhitespace = true;
xDoc.LoadXml("<xml/>");
xDoc.DocumentElement.CreateNavigator().AppendChild(r);
XmlNamespaceManager manager = new XmlNamespaceManager(xDoc.NameTable);
Once trying to parse I get: Unexpected xml declaration. The xml declaration must be the first node in the document ....
If I understand you correctly, then the data you are looking for starts after the SOAP envelope. There is no garbage/unnessescary contents after the data you are looking for.
The SOAP header does not start with the XML declaration (<?xml version=, etc).
Looking for the start of the document
A simple solution is to find the start of the XML document (the data you are looking for), and chop away everything before that.
var startOfRealDocumentMarker = "<?xml version=\"1.0\"";
var startIndex = dirtyXmlString.IndexOf(startOfRealDocumentMarker);
if(startIndex == -1) {
throw new Exception("Start of XML not found. Now what?");
}
var cleanXmlString = dirtyXmlString.Substring(startIndex);
If the SOAP header also has an XML declaration, you could look for the end-tag of the SOAP envelope instead. Or you could start looking for the declaration at the 2nd character, so you would skip over the first one.
This is obviously not a fool-proof solution that will work in every case. But maybe it will work in all of your cases?
Skipping lines
If you're sure it will work to always start reading from line 30 of the input file, you can use this method instead.
XmlDocument xDoc = new XmlDocument();
using (var rdr = new StreamReader(pathToXmlFile))
{
// Skip until reader is positioned at start of line 30
for (var i = 0; i < 29; ++i)
{
rdr.ReadLine();
}
// Load document from current position of reader
xDoc.Load(rdr);
}

using c# ignore a line with doctype from xml

i have developed a project in using c#, reads xml file and redirects the specified output in CSV file.
i am getting error in my code as from XDoc.LoadXml(filenamestr) it goes directly to catch block skipping the in between commands.
try
{
XmlDocument XDoc = new XmlDocument();
XDoc.LoadXml(filenamestr);
XmlDocumentType XDType = XDoc.DocumentType;
XDoc.RemoveChild(XDType);
XDoc.Save(filenamestr + ".xml");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
and error is
{"Data at the root level is invalid. Line 1, position 1."}
and the xml lines contains:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="MeasDataCollection.xsl"?>
<!DOCTYPE mdc SYSTEM "MeasDataCollection.dtd">
<mdc xmlns:HTML="http://www.w3.org/TR/REC-xml">
<mfh>
please help
You should change it
XDoc.LoadXml(filenamestr);
to
XDoc.Load(filenamestr);
LoadXml requires xml string instead of xml filename. You should Load method to load xml from file.

"Root element is missing" exception given when trying to parse XML file

I'm trying to set up parsing for a test XML generated with ksoap2 in Android:
<?xml version="1.0" encoding="utf-8"?>
<v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
<v:Header />
<v:Body>
<v:SOAPBODY>
<v:INFO i:type="v:INFO">
<v:LAITETUNNUS i:type="d:string">EI_TUNNUSTA</v:LAITETUNNUS>
</v:INFO>
<v:TOIMINNOT i:type="v:TOIMINNOT">
<v:TOIMINTA i:type="d:string">ASETUKSET_HAKU</v:TOIMINTA>
</v:TOIMINNOT>
<v:SISALTO i:type="v:SISALTO">
<v:KUVA i:type="d:string">AGFAFDGFDGFG</v:KUVA>
<v:MITTAUS i:type="d:string">12,42,12,4,53,12</v:MITTAUS>
</v:SISALTO>
</v:SOAPBODY>
</v:Body>
</v:Envelope>
But seemingly i can't parse it in any way. The exception is always that "Root element is not found" even when it goes through XML-validators like the one at w3schools. If i'm correct the contents of the body shouldn't be an issue when the problem is with root element.
The test code for parsing i try to use in C# is:
using (StreamReader streamreader = new StreamReader(Context.Request.InputStream))
{
try
{
XDocument xmlInput = new XDocument();
streamreader.BaseStream.Position = 0;
string tmp = streamreader.ReadToEnd();
var xmlreader = XmlReader.Create(streamreader.BaseStream);
xmlInput = XDocument.Parse(tmp);
xmlInput = XDocument.Load(xmlreader);
catch (Exception e)
{ }
where the xmlInput = XDocument.Parse(tmp); does indeed parse it to a XDocument, not a navigable one, though. Then xmlInput = XDocument.Load(xmlreader); throws the exception for not having a root element. I'm completely at loss here because i managed to parse and navigate the almost same xml with XMLDocument and XDocument classes before, and i fear i made some changes i didn't notice.
Thanks in advance.
Update: Here's the string tmp as requested :
"<?xml version=\"1.0\" encoding=\"utf-8\"?><v:Envelope xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\" xmlns:c=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:v=\"http://schemas.xmlsoap.org/soap/envelope/\"><v:Header /><v:Body><v:SOAPBODY><v:INFO i:type=\"v:INFO\"><v:LAITETUNNUS i:type=\"d:string\">EI_TUNNUSTA</v:LAITETUNNUS></v:INFO><v:TOIMINNOT i:type=\"v:TOIMINNOT\"><v:TOIMINTA i:type=\"d:string\">ASETUKSET_HAKU</v:TOIMINTA></v:TOIMINNOT><v:SISALTO i:type=\"v:SISALTO\"><v:KUVA i:type=\"d:string\">AGFAFDGFDGFG</v:KUVA><v:MITTAUS i:type=\"d:string\">12,42,12,4,53,12</v:MITTAUS></v:SISALTO></v:SOAPBODY></v:Body></v:Envelope>\r\n"
Update: Even with XDocument.Load(new StreamReader(Context.Request.InputStream, Encoding.UTF8)); the parsing will fail.
I believe you've read to the end of the stream once already, you need to reset the position in the stream again. see: "Root element is missing" error but I have a root element

Adding data to an existing xml file

I am using the follwing syntax to add data to already existing xml file in the following way:
XmlTextReader Reader = new XmlTextReader("ServerPaths.xml");
DataSet dsNewList = new DataSet();
dsNewList.ReadXml(Reader);
Reader.Close();
DataTable dt = dsNewList.Tables[0];
dt.Rows.Add(txtNewServerPath.Text);
dt.WriteXml("ServerPaths.xml",false);
But, i was getting error at last line as:
System.IO.IOException was unhandled
Message=The process cannot access the file 'C:\Documents and Settings\590000\my documents\visual studio 2010\Projects\EasyDeployer\EasyDeployer\bin\Debug\ServerPaths.xml' because it is being used by another process
Please help in solving this error. or is there any other way to do this?
My xml file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<ServerList>
<ServerPath>C:\\Avinash\\Dev1</ServerPath>
<ServerPath>C:\\Avinash\\Dev1</ServerPath>
</ServerList>
I just wanted to add new serverpath..
You could also try adding XmlNode's to the xml document like this:
XmlDocument xd = new XmlDocument();
xd.Load("ServerPaths.xml");
XmlNode rootNode = xd.DocumentElement;
XmlNode serverPathNode = xd.CreateElement("ServerPath");
serverPathNode.InnerText = txtNewServerPath.Text; // Your value
rootNode.AppendChild(serverPathNode);
xd.Save("ServerPaths.xml");

Convert string in xml document

I am getting some xml in a string variable through a wcf webservice. I need to confirm that the string xml I am getting is a valid xml or not.
and I would also like to convert this string to xml document for further processing.
Please let me know how to do it.
How about using XDocument.Parse()
string str =
#"<?xml version=""1.0""?>
<!-- comment at the root level -->
<Root>
<Child>Content</Child>
</Root>";
XDocument doc = XDocument.Parse(str);
Console.WriteLine(doc);
Or if you want to catch the parsing error, use try/catch:
try {
XElement contacts = XElement.Parse(
#"<Contacts>
<Contact>
<Name>Jim Wilson</Name>
</Contact>
</Contcts>");
Console.WriteLine(contacts);
}
catch (System.Xml.XmlException e)
{
Console.WriteLine(e.Message);
}
try to use XElement.Parse :
http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.parse.aspx
I think you can validate the wcf response xml with MessageInspector.MSDN contains a worked example of how this can be accomplished using WCF MessageInspectors

Categories