Alex Rivera | Logout

An error has occurred opening extern DTD (w3.org, xhtml1-transitional.dtd). 503 Server Unavailable

Asked 2010-04-01T03:49:20.103
10

I'm trying to do xpath queries over an xhtml document. Using .NET 3.5.

The document looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
   ....
  </head>
  <body>
    ...
  </body>
</html>

Because the document includes various char entities (&nbsp; and so on), I need to use the DTD, in order to load it with an XmlReader. So my code looks like this:

var s = File.OpenRead(fileToRead)
var reader = XmlReader.Create(s, new XmlReaderSettings{ ProhibitDtd=false });

But when I run this, it returns

An error has occurred while opening external DTD 'http://www.w3.org/TR/xhtml1-transitional.dtd': The remote server returned an error: (503) Server Unavailable.

Now, I know why I am getting the 503 error. W3C explained it very clearly.

I've seen "workarounds" where people just disable the DTD. This is what ProhibitDtd=true can do, and it eliminates the 503 error.

But in my case that leads to other problems - the app doesn't get the entity defintions and so isn't well-formed XML. How can I validate with the DTD, and get the entity definitions, without hitting the w3.org website?


I think .NET 4.0 has a nifty built-in capability to handle this situation: the .net xml xhtml w3c dtd

Edit
Report

1 Answer

2

When your ResolveUri method gets a request for a "public" form of the URI like -//W3C//ELEMENTS XHTML Images 1.0//EN then does your method throw and wait for the subsequent web-like URI which begins with http://?

Instead of throwing, I resolve the public URI to the corresponding http:// URI (and then in my GetEntity method I intercept requests to the http:// URIs).

I therefore never have to throw, which I think is the right solution.


That's a smart way to do it. How big is your dictionary? The library I pointed you to handles only XHTML 1.0, and there is just one public URI base that would need to be mapped.

I'm using XHTML 1.1 which is 'modular' so I have to map about 40 files.

Beware that the Framework's behaviour may have changed! I have a library (including my XhtmlUrlResolver class) which is built with the .NET Framework 2, but it's invoked differently depending on whether the application (which uses the library) is build for .NET 2 or .NET 4.

With .NET 2, when my ResolveUri method always only delegated transparently to a XmlUrlResolver, then it would:

  1. Ask to ResolveUri the public of the DTD.
  2. Try to GetEntity the DTD from disk (throws one DirectoryNotFoundException)
  3. Try to GetEntity the DTD from http (which I'd serve from local resources)
  4. Try to GetEntity every other file from http (which I'd serve from local resources)

With .NET 4 there was an extra call for every resource:

  • Ask to ResolveUri the public of the sub-resource (e.g. the *.mod file), which my implementation just delegated to XmlUrlResolver
  • Ask to GetEntity the 'resolved' public of the sub-resource, which wasn't really resolved at all, it just had an http-like prefix added (throws WebException)

Throwing all those WebExceptions slowed

answered 2010-11-11T10:29:46.163

Your Answer