Skip to main content
GameDev.net gamedev.net
🔒 Locked

[.net] Validating XML documents

Started by capn_midnight Jul 5, 2005 at 2:53 PM 5 replies 3.5k views
Original Post
capn_midnight
capn_midnight
I'm writing a fairly large module to our product here at work (READ: I really can't show you very much code). I'm having a problem loading documents that define a DTD, e.g. GDNet RSS. Documents without DTD definitions load fine, e.g. CNN World News RSS. My problem is specifically limited to this bit of code (the minimum amount of code to replicate the problem)

XmlTextReader reader = new XmlTextReader("http://www.gamedev.net/xml/");
XmlDocument doc = new XmlDocument();
doc.Load(reader);
I've tried using validating readers (I believe this is the code in the msdn examples on using XmlDocuments)

XmlTextReader reader = new XmlTextReader("http://www.gamedev.net/xml/");
XmlValidatingReader validator = new XmlValidatingReader(reader);
validator.ValidationType = ValidationType.DTD;
XmlDocument doc = new XmlDocument();
doc.Load(validator);
but to no avail. Each block dies on the call to doc.Load().

Unhandled Exception: System.Xml.XmlException: The expected DTD markup was not fo
und. Line 1, position 3.
   at System.Xml.XmlScanner.ScanDtdContent()
   at System.Xml.Schema.DtdParser.ScanDtdContent()
   at System.Xml.Schema.DtdParser.ParseDtdContent()
   at System.Xml.Schema.DtdParser.ParseDocTypeDecl()
   at System.Xml.Schema.DtdParser.Parse()
   at System.Xml.XmlTextReader.ParseDtd(XmlScanner scanner)
   at System.Xml.XmlTextReader.ParseTag()
   at System.Xml.XmlTextReader.ParseRoot()
   at System.Xml.XmlTextReader.Read()
   at System.Xml.XmlValidatingReader.ReadWithCollectTextToken()
   at System.Xml.XmlValidatingReader.Read()
   at System.Xml.XmlLoader.LoadCurrentNode()
   at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean prese
rveWhitespace)
   at System.Xml.XmlDocument.Load(XmlReader reader)
   at RssReader.Class1.Main(String[] args) in c:\documents and settings\smcbethmy documents\visual studio projects\rssreader\class1.cs:line 20

I'm using .Net framework v1.1 and if you really want to know, I'm using C#, Visual Studio.Net 2003, and I got the RSS 2.0 spec from Harvard Law. Quite frankly, it's the worst excuse for a spec I have ever read, but atleast the spec itself is pretty simple. Funny, the IRC spec was horrifying, but atleast the spec document was official and technical.
jods
jods
I'm not sure, but try this:
XmlValidatingReader reader = new XmlValidatingReader("http://www.gamedev.net/xml/");reader.XmlResolver = new XmlUrlResolver();

The XmlResolver is used to grab external resources referred to by the xml document, like a DTD.

Other idea for a workaround: turn off DTD validation ?

Hope it helps,
jods
capn_midnight
capn_midnight
ARGH! If I try to read the gdnet stream from the web, it gives me the error. If I save the gdnet stream as an xml file on my local disk, and THEN read it, I get no error.

Edit: It doesn't error out immediately. It's able to read the first line of the document (the xml version), but after that, it dies.

[Edited by - capn_midnight on July 6, 2005 1:19:31 PM]
capn_midnight
capn_midnight
Okay, so I can't read ANY version of RSS feeds that contain some form of validation *from the web*. I can first save the feed to disk, and THEN read the file, still with the validation, and it will validate and read. But if I pass the regular URL, it bongs out.

And setting the ValidationType to None apparently does nothing. It still attempts to validate the XML document and still fails.

ARGH! I really want to get this working. This is rediculous! I've copied the MSDN code on using XmlValidatingReaders *word-for-word*. Someone has to have some ideas here.

Here is a complete set of code for you
using System;using System.Xml;namespace RssReader{	/// <summary>	/// Summary description for Class1.	/// </summary>	class Class1	{		static int i = 0;		/// <summary>		/// The main entry point for the application.		/// </summary>		static void Main(string[] args)		{			//saved via Internet Explorer -WORKS!			Load("../../Data/gdnet.xml");			//manually cached to disk -WORKS!			System.Net.WebRequest wr = System.Net.WebRequest.Create("http://www.gamedev.net/xml");			System.Net.WebResponse wresp = wr.GetResponse();			System.IO.StreamReader sr = new System.IO.StreamReader(wresp.GetResponseStream());			System.IO.StreamWriter sw = new System.IO.StreamWriter("temp.xml");			sw.Write(sr.ReadToEnd());			sw.Close();			sr.Close();			wresp.Close();			Load("temp.xml");			//loaded direct from web -FAILS!			Load("http://www.gamedev.net/xml/");		}		static void Summarize(Rss.Feed feed)		{			Console.WriteLine("<{0}>\n\t{1}\n</{0}>",feed.Channel.Title, feed.Channel.Description);		}		static void Load(string URL)		{			Console.WriteLine("Attempting load #{0}: {1}",i, URL);			XmlTextReader reader = new XmlTextReader(URL);			reader.Read();			Console.WriteLine("   reader has value: {0}",reader.Value);			XmlValidatingReader validator = new XmlValidatingReader(reader);			validator.ValidationType = ValidationType.None;			Console.WriteLine("   validator has value: {0}", validator.Value);						XmlDocument doc = new XmlDocument();			doc.Load(validator);			Console.WriteLine("   document's first child has value: {0}", doc.FirstChild.Value);			if(doc.HasChildNodes)			{				Console.WriteLine("      Document has {0} child nodes.", doc.ChildNodes.Count);			}			Console.WriteLine("Succesful load #{0}\n",i++);		}	}}

And output
Attempting load #0: ../../Data/gdnet.xml   reader has value: version="1.0"   validator has value: version="1.0"   document's first child has value:      Document has 2 child nodes.Succesful load #0Attempting load #1: temp.xml   reader has value: version="1.0"   validator has value: version="1.0"   document's first child has value:      Document has 2 child nodes.Succesful load #1Attempting load #2: http://www.gamedev.net/xml/   reader has value: version="1.0"   validator has value: version="1.0"Unhandled Exception: System.Xml.XmlException: The expected DTD markup was not found. Line 1, position 3.   at System.Xml.XmlScanner.ScanDtdContent()   at System.Xml.Schema.DtdParser.ScanDtdContent()   at System.Xml.Schema.DtdParser.ParseDtdContent()   at System.Xml.Schema.DtdParser.ParseDocTypeDecl()   at System.Xml.Schema.DtdParser.Parse()   at System.Xml.XmlTextReader.ParseDtd(XmlScanner scanner)   at System.Xml.XmlTextReader.ParseTag()   at System.Xml.XmlTextReader.ParseRoot()   at System.Xml.XmlTextReader.Read()   at System.Xml.XmlValidatingReader.ReadWithCollectTextToken()   at System.Xml.XmlValidatingReader.Read()   at System.Xml.XmlLoader.LoadCurrentNode()   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 RssReader.Class1.Load(String URL) in c:\documents and settings\smcbeth\mydocuments\visual studio projects\rssreader\class1.cs:line 56   at RssReader.Class1.Main(String[] args) in c:\documents and settings\smcbethmy documents\visual studio projects\rssreader\class1.cs:line 37Press any key to continue


[Edited by - capn_midnight on July 11, 2005 10:57:54 AM]
capn_midnight
capn_midnight
In case anyone has this problem in the future, I have found a fix/workaround. Instead of loading the document by supplying the URL to the feed to the XmlTextReader, use the System.IO.Stream from a System.Net.WebResponce obtained from a System.Net.WebRequest to the URL to initiallize the XmlTextReader (a mouthfull, I know).
//don't do this for RSS 0.91 using a DTD for validationSystem.Xml.XmlTextReader reader = new System.Xml.XmlTextReader("http://www.gamedev.net/xml");//instead do thisSystem.Net.WebRequest request = System.Net.WebRequest.Create("http://www.gamedev.net/xml");System.Net.WebResonce responce = request.GetResponce();System.IO.Stream stream = responce.GetStream();System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(stream);
capn_midnight
capn_midnight
Well, I can't show you the actual application, but I can show you a cropped screencap of the module I was writing (since it's all public information). It came out pretty well, I think.
Cybrosys
Cybrosys
Very nice, thanks for following through with your solution as well and not just dropping the topic =)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.