Search code examples
c#xmlxml-parsingxmlreaderdtd

Reference to undeclared entity &copy


When I process the XML files using C#, I get this error. I searched previous questions and found the reason. I understand these entities are not predefined in XML and must be included in DTD. It is included in the DTD. My XML files include the following DTD.

<!DOCTYPE doc PUBLIC "-//Location//EN"    
 "NAME.dtd" [
<!ENTITY C-1FHY "SD FFF">
<!ENTITY Ca- "XX">
]>

Also

I need to read content from this XML file. I used XMLReader.

  XmlReaderSettings settings = new XmlReaderSettings();


                settings.DtdProcessing = DtdProcessing.Parse;

                XmlReader doc = XmlReader.Create(f, settings);
                while (doc.Read())
                {

If I ignore DTD, it throws the error. If I parse, then it says it couldnt find the DTD in the location where every file is. If I copy the DTD in the same location where the file is, i dont have any problem.

My problem is there are 500+ docs in more than 60+ sub folders. I can't put a copy of the DTD in every folder. Is there a way I store a single copy of DTD in a path and link it in the code? Please help me in this.


Solution

  • You can make a custom XmlUrlResolver that remaps the file location:

    public class XmlUrlOverrideResolver : XmlUrlResolver
    {
        public Dictionary<string, string> DtdFileMap { get; private set;  }
    
        public XmlUrlOverrideResolver()
        {
            this.DtdFileMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        }
    
        public override Uri ResolveUri(Uri baseUri, string relativeUri)
        {
            string remappedLocation;
            if (DtdFileMap.TryGetValue(relativeUri, out remappedLocation))
                return new Uri(remappedLocation);
            var value = base.ResolveUri(baseUri, relativeUri);
            return value;
        }
    }
    

    And then use it like:

            var resolver = new XmlUrlOverrideResolver();
            resolver.DtdFileMap[@"NAME.dtd"] = @"C:\Location\Of\File\name.dtd";
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.DtdProcessing = DtdProcessing.Parse;
            settings.XmlResolver = resolver;
    
            // Proceed as before.