Отсутствует загрузка VDS.RDF.Parsing.RdfXmlParser (обработчик IRdfHandler, документ XmlDocument) - PullRequest
0 голосов
/ 30 сентября 2019

Я ищу перегрузку с вышеупомянутой подписью.

Мне нужно загрузить из XmlDocument, потому что загрузка из файла owl напрямую или через поток приводит к ошибке:

"Входной документ превысил предел, установленный MaxCharactersFromEntities."

Есть ли что-то очевидное, о чем я не знаю?

Спасибо, Ян

Редактировать 1 - Добавление кода, показывающего исключение

Я пытаюсь проанализировать онтологию клеточной линии (~ 100 МБ). Поскольку мне нужен только определенный контент, я бы хотел использовать обработчик, чтобы сосредоточиться на интересных вещах. Для демонстрации моей проблемы я использую CountHandler

private static void loadCellLineOntology()
    {
        try
        {
            var settings = new System.Xml.XmlReaderSettings()
            {
                MaxCharactersFromEntities = 0,
                DtdProcessing = System.Xml.DtdProcessing.Parse
            };

            var doc = new System.Xml.XmlDocument();
            var parser = new VDS.RDF.Parsing.RdfXmlParser(VDS.RDF.Parsing.RdfXmlParserMode.DOM);

            //using (var stream = new System.IO.FileStream(@"C:\Users\jan.hummel\Downloads\clo.owl", System.IO.FileMode.Open))
            //using (var reader = System.Xml.XmlReader.Create(stream, settings))
            using (IGraph g = new NonIndexedGraph())
            {
                //doc.Load(reader);
                //parser.Load(g, @"C:\Users\jahu\Downloads\clo.owl");

                var handler = new VDS.RDF.Parsing.Handlers.CountHandler();
                parser.Load(handler, @"C:\Users\jahu\Downloads\clo.owl");
                //parser.Load(handler, doc);
            }
        }
        catch (Exception ex)
        {
            Debugger.Break();
        }
    }

1 Ответ

1 голос
/ 01 октября 2019

Нет ничего очевидного. Перегрузка, которую вы ищете, не существует, и инфраструктура синтаксического анализатора RDF / XML не позволяет вам установить XmlReaderSettings.MaxCharactersFromEntities.

. Я смог обойти эту проблему, реплицировав соответствующие частисинтаксический анализатор настолько далеко, чтобы изменить эту настройку. Остерегайтесь, это полагается на внутренние детали реализации, следовательно, вся частная диспетчеризация использует Reflection.

. Интересный бит находится в CellLineOntology.RdfXmlParser.Context.Generator.ctor(Stream).

. Если у вас есть код ниже, вы можете позвонить

var handler = new VDS.RDF.Parsing.Handlers.CountHandler();
CellLineOntology.RdfXmlParser.Load(handler, @"..\..\..\..\clo.owl");

Я получил количество 1 387 097 заявлений, используя файл, который вы связали.


namespace CellLineOntology
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Xml;
    using VDS.RDF;
    using VDS.RDF.Parsing.Contexts;
    using VDS.RDF.Parsing.Events;
    using VDS.RDF.Parsing.Events.RdfXml;
    using VDS.RDF.Parsing.Handlers;

    internal class RdfXmlParser
    {
        public static void Load(IRdfHandler handler, string filename)
        {
            using (var input = File.OpenRead(filename))
            {
                Parse(new Context(handler, input));
            }
        }

        private static void Parse(RdfXmlParserContext context) => typeof(VDS.RDF.Parsing.RdfXmlParser).GetMethod("Parse", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(new VDS.RDF.Parsing.RdfXmlParser(), new[] { context });

        private class Context : RdfXmlParserContext
        {
            private IEventQueue<IRdfXmlEvent> _queue
            {
                set => typeof(RdfXmlParserContext).GetField("_queue", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, value);
            }

            public Context(IRdfHandler handler, Stream input)
                : base(handler, Stream.Null)
            {
                _queue = new StreamingEventQueue<IRdfXmlEvent>(new Generator(input, ToSafeString(GetBaseUri(handler))));
            }

            private static Uri GetBaseUri(IRdfHandler handler) => (Uri)typeof(HandlerExtensions).GetMethod("GetBaseUri", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new[] { handler });

            private static string ToSafeString(Uri uri) => (uri == null) ? string.Empty : uri.AbsoluteUri;

            private class Generator : StreamingEventGenerator
            {
                private XmlReader _reader
                {
                    set => typeof(StreamingEventGenerator).GetField("_reader", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, value);
                }

                private bool _hasLineInfo
                {
                    set => typeof(StreamingEventGenerator).GetField("_hasLineInfo", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, value);
                }

                private string _currentBaseUri
                {
                    set => typeof(StreamingEventGenerator).GetField("_currentBaseUri", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, value);
                }

                public Generator(Stream stream)
                    : base(Stream.Null)
                {
                    var settings = GetSettings();

                    // This is why we're here
                    settings.MaxCharactersFromEntities = 0;

                    var reader = XmlReader.Create(stream, settings);

                    _reader = reader;
                    _hasLineInfo = reader is IXmlLineInfo;
                }

                public Generator(Stream stream, string baseUri)
                    : this(stream)
                {
                    _currentBaseUri = baseUri;
                }

                private XmlReaderSettings GetSettings() => (XmlReaderSettings)typeof(StreamingEventGenerator).GetMethod("GetSettings", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, null);
            }
        }
    }
}
...