Home > database >  How can I process doc types when reading fragments?
How can I process doc types when reading fragments?

Time:12-19

I have a list of xml entities I would like to support and read without processing. Therefore I am creating a custom doc type where I register these entities:

xml = "<!DOCTYPE doctypeName [\r\n   <!ENTITY nbsp \"LINE BREAK\">\r\n]>  "   xml;

Then I set the entity handling accordingly:

reader.EntityHandling = EntityHandling.ExpandCharEntities;

This works fine. But I also have to read fragments. But when I try to read the fragment with the same approach I get the following error:

// System.Xml.XmlException: 'Unexpected DTD declaration. Line 1, position 3.'

var reader = XmlReader.Create(new StringReader(xxml2), new XmlReaderSettings
{
    DtdProcessing = DtdProcessing.Parse,
    ConformanceLevel = ConformanceLevel.Fragment,
}, context);

The fragment is used inside the reading process of the normal reader, so if there is some kind of context to reuse or a child reader, this would work as well.

Is there are an option to use fragments an doctypes together?

CodePudding user response:

There indeed is a class https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlparsercontext?view=net-7.0 you can create and pass in on XmlReader.Create() e.g. with overloads like https://learn.microsoft.com/de-de/dotnet/api/system.xml.xmlreader.create?view=net-7.0#system-xml-xmlreader-create(system-string-system-xml-xmlreadersettings-system-xml-xmlparsercontext). The parser context allows you set DTD information like the subset.

Minimal example:

using System.Xml;

const string subset = "<!ENTITY nbsp '&#160;'>";

const string fragment = "This is important:&nbsp;Use a parser context.";

using (XmlReader xr = XmlReader.Create(
       new StringReader(fragment), 
       new XmlReaderSettings() { 
           ConformanceLevel = ConformanceLevel.Fragment, 
           DtdProcessing = DtdProcessing.Parse }, 
       new XmlParserContext(new NameTable(), null, "html", null, null, subset, null, null, XmlSpace.Default)))

{
    while (xr.Read())
    {
        Console.WriteLine(xr.Value);
    }

}
  • Related