Буфер XmlReader, кажется, игнорирует изменения в буфере?

Возможно, мое понимание того, что должно произойти, неверно, так что, надеюсь, кто-то сможет исправить мой мыслительный процесс здесь.

Я пытаюсь обработать много больших XML-файлов, которые постоянно отправляются нам с плохими символами, встроенными в текст (0x1A)... к сожалению, наш клиент отправляет файлы, так что как бы мы ни просили их сделать файлы на самом деле являются действительными XML, они считают это нашей проблемой.

В конце концов я написал подкласс StreamReader вот так:

public class CleanTextReader : StreamReader
{
    private readonly ILog _logger;

    public CleanTextReader(Stream stream, ILog logger) : base(stream)
    {
        this._logger = logger;
    }

    public CleanTextReader(Stream stream) : this(stream, LogManager.GetLogger<CleanTextReader>())
    {
        //nothing to do here.
    }
    public override int Read(char[] buffer, int index, int count)
    {
        try
        {
            var rVal = base.Read(buffer, index, count);

            var filteredBuffer = buffer.Select(x => XmlConvert.IsXmlChar(x) ? x : ' ').ToArray();

            Buffer.BlockCopy(filteredBuffer, 0, buffer, 0, count);
            return rVal;
        }
        catch (Exception ex)
        {
            this._logger.Error("Read(char[], int, int)", ex);
            throw;
        }
    }

    public override int ReadBlock(char[] buffer, int index, int count)
    {
        try
        {
            var rVal = base.ReadBlock(buffer, index, count);
            var filteredBuffer = buffer.Select(x => XmlConvert.IsXmlChar(x) ? x : ' ').ToArray();
            Buffer.BlockCopy(filteredBuffer, 0, buffer, 0, count);
            return rVal;
        }
        catch (Exception ex)
        {
            this._logger.Error("ReadBlock(char[], in, int)", ex);
            throw;
        }
    }

    public override string ReadToEnd()
    {
        var chars = new char[4096];
        int len;
        var sb = new StringBuilder(4096);
        while ((len = Read(chars, 0, chars.Length)) != 0)
        {
            sb.Append(chars, 0, len);
        }
        return sb.ToString();
    }
}

... тогда я реализую XmlReader вот так:

using (var theCleanser = new CleanTextReader(myStreamedInput))
using (var theReader = XmlReader.Create(theCleanser))
{
    ...
    // do stuff with theReader
}

У меня есть модульный тест, как так:

    [TestMethod]
    public void CleanTextReaderCleans0X1A()
    {
        //arrange
        var originalString = "The quick brown fox jumped over the lazy dog.";
        var badChars = new string(new[] {(char) 0x1a});
        var concatenated = originalString.Replace("jumped", badChars + "jumped" + badChars);

        //act
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(concatenated)))
        {
            using (var reader = new CleanTextReader(stream))
            {
                var newString = reader.ReadToEnd().Trim().Replace("  ", " ");
                //assert
                Assert.IsTrue(originalString.Equals(newString));
            }
        }
    }

... это проходит.

но когда я пытаюсь разобрать файл XML с символом 0x1A, я все равно получаю System.Xml.XmlException: '', шестнадцатеричное значение 0x1A, является недопустимым символом. Строка XX, позиция XX

Копаем глубже в CleanTextReader Я изучаю Read(char[], int, int) метод, как кажется, поражен XmlReader, Оригинал buffer имеет недопустимые символы, но filteredBuffer нет, и после Buffer.BlockCopy() работает, оба buffer и filteredBuffer лишены специальных символов.

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

Так что я чешу голову здесь. Как работает XmlReader получить специальные символы? Это чтение из буфера до того, как управление вернется из метода? Как мне исправить эту проблему?

ОБНОВИТЬ

по запросу я получаю трассировку стека:

"System.Xml.XmlException: '', hexadecimal value 0x1A, is an invalid character. Line 84, position 38.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args)
   at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars)
   at System.Xml.XmlTextReaderImpl.ParseText()
   at System.Xml.XmlTextReaderImpl.ParseElementContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r)
   at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r, LoadOptions o)
   at System.Xml.Linq.XElement.ReadElementFrom(XmlReader r, LoadOptions o)
   at System.Xml.Linq.XNode.ReadFrom(XmlReader reader)
   at MyCompany.Importers.GroupEligibilityModel.Loader.<GetGroupEligibilityElements>d__2b.MoveNext() in c:\\Projects\\MyCompanyHealth\\MyCompany.Importers\\MyCompany.Importers.GroupEligibilityModel\\MyCompany.Importers.GroupEligibilityModel\\Loader.cs:line 138
   at MyCompany.Importers.GroupEligibilityModel.Loader.<GetGroupEligibilities>d__18.MoveNext() in c:\\Projects\\MyCompanyHealth\\MyCompany.Importers\\MyCompany.Importers.GroupEligibilityModel\\MyCompany.Importers.GroupEligibilityModel\\Loader.cs:line 71
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at MyCompany.Importers.GroupEligibilityModel.Test.LoadingTests.GroupEligibilityFileWithBadCharactersProperlyCleansed() in c:\\Projects\\MyCompanyHealth\\MyCompany.Importers\\MyCompany.Importers.GroupEligibilityModel\\MyCompany.Importers.GroupEligibilityModel.Test\\LoadingTests.cs:line 118"   string

0 ответов

Другие вопросы по тегам