Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>When your <code>ResolveUri</code> method gets a request for a "public" form of the URI like <code>-//W3C//ELEMENTS XHTML Images 1.0//EN</code> then does your method throw and wait for the subsequent web-like URI which begins with <code>http://</code>?</p> <p>Instead of throwing, I resolve the public URI to the corresponding <code>http://</code> URI (and then in my <code>GetEntity</code> method I intercept requests to the <code>http://</code> URIs).</p> <p>I therefore never have to throw, which I think is the right solution.</p> <hr> <blockquote> <p>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.</p> </blockquote> <p>I'm using XHTML 1.1 which is 'modular' so I have to map about 40 files.</p> <p>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.</p> <p>With .NET 2, when my ResolveUri method always only delegated transparently to a XmlUrlResolver, then it would:</p> <ol> <li>Ask to ResolveUri the public of the DTD.</li> <li>Try to GetEntity the DTD from disk (throws one DirectoryNotFoundException)</li> <li>Try to GetEntity the DTD from http (which I'd serve from local resources)</li> <li>Try to GetEntity every other file from http (which I'd serve from local resources)</li> </ol> <p>With .NET 4 there was an extra call for every resource:</p> <ul> <li>Ask to ResolveUri the public of the sub-resource (e.g. the <code>*.mod</code> file), which my implementation just delegated to XmlUrlResolver</li> <li>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)</li> </ul> <p>Throwing all those WebExceptions slowed down processing a lot, which is why I revisited this to look for a fix.</p> <p>Your suggestion, that I throw from ResolveUri, solved that problem, for which I thank you; but instead of throwing, returning something from ResolveUri is more elegant (and a bit faster: 40 fewer exceptions).</p> <p>Here's my current source code.</p> <pre><code>using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.IO; using System.Xml; //don't obfuscate the file names of the embedded resources, //which are contained in a "Files" subfolder of the project [assembly: Obfuscation(Feature = "Apply to ModelText.ModelXml.Files.*: all", Exclude = true, ApplyToMembers = true)] namespace ModelText.ModelXml { /// &lt;summary&gt; /// This class provides local (i.e. faster) access to the XHTML DTD. /// &lt;/summary&gt; /// &lt;remarks&gt; /// Another way to implement this class is described in MSDN "Customizing the XmlUrlResolver Class" /// which shows as an example a "class XmlCachingResolver" /// and which is implemented using WebRequest and HttpRequestCachePolicy /// &lt;/remarks&gt; [System.Reflection.ObfuscationAttribute(Feature = "renaming", ApplyToMembers = true)] public class XhtmlUrlResolver : XmlResolver { XmlUrlResolver m_xmlUrlResolver = new XmlUrlResolver(); Assembly m_assembly = Assembly.GetExecutingAssembly(); public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) { string uriString = absoluteUri.ToString(); if (s_resources.uriExists(uriString)) { //Console.WriteLine("XhtmlUrlResolver Found {0} -- {1}", uriString, DateTime.Now); //to get the filename of the embedded resource, remove the http: directory //this is OK because the filenames are unique and map 1-to-1 with resource names string filename = uriString.Substring(uriString.LastIndexOf('/') + 1); Stream stream = m_assembly.GetManifestResourceStream(typeof(XhtmlUrlResolver), "Files." + filename); return stream; } //Console.WriteLine("XhtmlUrlResolver Throwing {0} -- {1}", uriString, DateTime.Now); throw new ArgumentException(); //Console.WriteLine("XhtmlUrlResolver Getting {0} -- {1}", uriString, DateTime.Now); //object o = m_xmlUrlResolver.GetEntity(absoluteUri, role, ofObjectToReturn); //Console.WriteLine("XhtmlUrlResolver Got {0} -- {1}", uriString, DateTime.Now); //return o; } public override Uri ResolveUri(Uri baseUri, string relativeUri) { string resolved = s_resources.resolve(relativeUri); if (resolved != null) { //Console.WriteLine("ResolveUri resolving {0}, {1} -- {2}", baseUri, relativeUri, DateTime.Now); return new Uri(resolved); } //Console.WriteLine("ResolveUri passing {0}, {1} -- {2}", baseUri, relativeUri, DateTime.Now); return m_xmlUrlResolver.ResolveUri(baseUri, relativeUri); } public override System.Net.ICredentials Credentials { set { m_xmlUrlResolver.Credentials = value; } } static Resources s_resources = new Resources(); class Resources { Dictionary&lt;string, string&gt; m_publicToUri = new Dictionary&lt;string, string&gt;(); internal Resources() { for (int i = 0, n = array.GetLength(0); i &lt; n; ++i) { m_publicToUri.Add(array[i, 1], array[i, 0]); } } internal bool uriExists(string absoluteUri) { return m_publicToUri.ContainsValue(absoluteUri); } internal string resolve(string relativeUri) { string resolved; if (m_publicToUri.TryGetValue(relativeUri, out resolved)) { return resolved; } return null; } static string[,] array = { { "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", "-//W3C//DTD XHTML 1.1//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml11-model-1.mod", "-//W3C//ENTITIES XHTML 1.1 Document Model 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-attribs-1.mod", "-//W3C//ENTITIES XHTML Common Attributes 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-base-1.mod", "-//W3C//ELEMENTS XHTML Base Element 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-bdo-1.mod", "-//W3C//ELEMENTS XHTML BIDI Override Element 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-blkphras-1.mod", "-//W3C//ELEMENTS XHTML Block Phrasal 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-blkpres-1.mod", "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-blkstruct-1.mod", "-//W3C//ELEMENTS XHTML Block Structural 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-charent-1.mod", "-//W3C//ENTITIES XHTML Character Entities 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-csismap-1.mod", "-//W3C//ELEMENTS XHTML Client-side Image Maps 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-datatypes-1.mod", "-//W3C//ENTITIES XHTML Datatypes 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-edit-1.mod", "-//W3C//ELEMENTS XHTML Editing Elements 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-events-1.mod", "-//W3C//ENTITIES XHTML Intrinsic Events 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-form-1.mod", "-//W3C//ELEMENTS XHTML Forms 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-framework-1.mod", "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-hypertext-1.mod", "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-image-1.mod", "-//W3C//ELEMENTS XHTML Images 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-inlphras-1.mod", "-//W3C//ELEMENTS XHTML Inline Phrasal 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-inlpres-1.mod", "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-inlstruct-1.mod", "-//W3C//ELEMENTS XHTML Inline Structural 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-inlstyle-1.mod", "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-lat1.ent", "-//W3C//ENTITIES Latin 1 for XHTML//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-link-1.mod", "-//W3C//ELEMENTS XHTML Link Element 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-list-1.mod", "-//W3C//ELEMENTS XHTML Lists 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-meta-1.mod", "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-object-1.mod", "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-param-1.mod", "-//W3C//ELEMENTS XHTML Param Element 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-pres-1.mod", "-//W3C//ELEMENTS XHTML Presentation 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-qname-1.mod", "-//W3C//ENTITIES XHTML Qualified Names 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-script-1.mod", "-//W3C//ELEMENTS XHTML Scripting 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-special.ent", "-//W3C//ENTITIES Special for XHTML//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-ssismap-1.mod", "-//W3C//ELEMENTS XHTML Server-side Image Maps 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-struct-1.mod", "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-style-1.mod", "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-symbol.ent", "-//W3C//ENTITIES Symbols for XHTML//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-table-1.mod", "-//W3C//ELEMENTS XHTML Tables 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-target-1.mod", "-//W3C//ELEMENTS XHTML Target 1.0//EN" }, { "http://www.w3.org/MarkUp/DTD/xhtml-text-1.mod", "-//W3C//ELEMENTS XHTML Text 1.0//EN" }, { "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod", "-//W3C//ELEMENTS XHTML Ruby 1.0//EN" } }; } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload