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 ' '>";
const string fragment = "This is important: 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);
}
}