2015-10-09 3 views
0

У меня есть XML с недопустимыми шестнадцатеричными символами. Я прочитал this, this и this и любые другие ссылки, но не смогли заставить его работать.Недопустимые шестнадцатеричные символы в XML

Я использую XmlReader - XmlDocument, XDocument и XmlTextReader не мои варианты, потому что есть XML-файлы с более размером 500 ГБ и 500 миллионов в объеме. XMLReader - мой лучший выбор из-за его «прямого» подхода, а не загрузки в память всех деталей XML. Кроме того, из-за этого у меня не может быть восстановлен или загружен XML-файл только для замены недопустимых символов.

Вот код, который я работаю над:

case XmlNodeType.Element: 
if (xmlReader.Name.Equals("ROW")) 
{ 
    DataRow dataRow = xmlDataTable.NewRow(); 
    XmlReader row = XmlReader.Create(xmlReader.ReadSubtree(), new XmlReaderSettings { CheckCharacters = false 
                      , ValidationType = ValidationType.None }); 

    // iterate on elements inside ROW 
    // these are the column items 
    if (row != null) 
    { 
     while (row.Read()) 
     { 

      if (row.IsStartElement()) 
      { 

       if (!row.Name.Equals("ROW")) 
       { 

        string columnName = row.Name; 
        //row = XmlReader.Create(CleanInvalidXmlChars(row.ReadInnerXml())); 

        row.Read(); 
        string value = CleanInvalidXmlChars(row.Value.ToString()); 

        // all other logics ... 

Исключение поднимает на row.Read(); заявление. Вот пример XML-файла, который я читаю:

<?xml version="1.0" encoding="UTF-8"?> 
<MFAINSBRP> 
<ROW> 
    <INSTITUTION_CODE>828 </INSTITUTION_CODE> 
    <BRANCH_CODE>GJ102</BRANCH_CODE> 
    <BRANCH_NAME>         </BRANCH_NAME> 
    <BRANCH_NAME_FRENCH>         </BRANCH_NAME_FRENCH> 
    <LANGUAGE_CODE>E</LANGUAGE_CODE> 
    <ADDR_NO>815412</ADDR_NO> 
    <FAX_AREA>0</FAX_AREA> 
    <FAX_PHONE>0</FAX_PHONE> 
    <AREA_CODE>0</AREA_CODE> 
    <PHONE_NO>0</PHONE_NO> 
    <STATUS>A</STATUS> 
    <PHONE_EXT>0</PHONE_EXT> 
</ROW> 
<!--ALL OTHER RECORDS--> 
</MFAINSBRP> 

Прямо сейчас, я застрял на выполнении этой работы.

EDIT:

Образец XML-файл является запись, которая делает мой код перерыв. Я скопировал его, вставил его здесь из Notepad ++, но он не показывает недопустимые символы. Вот образ того, как она выглядит в Notepad ++:

enter image description here

Как создать xmlReader объект только это простое утверждение:

using (xmlReader = XmlReader.Create(filePath, new XmlReaderSettings { CheckCharacters = false })) 
+0

Где в файле это не удается? Я ожидаю, что исключение покажет вам строку/столбец. –

+0

В этом примере XML содержится пример ввода проблемы, который нарушит ваш код? Если да, не могли бы вы выделить его каким-то образом? Если нет, можете ли вы создать образец, который * показывает * проблему? –

+0

http://stackoverflow.com/questions/5742543/an-invalid-xml-character-unicode-0xc-was-found может быть связано.Файл ошибочен, поэтому вам нужно предварительно обработать его и сначала удалить оскорбительные символы. Возможно, вы сможете сделать это с промежуточным потоком. – jishi

ответ

1

Неясно мне, почему CheckCharacters = false не фиксируя проблемы для вас, и, как я уже упомянул , далекое, далекое лучше исправить, чтобы получить данные в чистом виде.

Однако вы можете обойти это, заменив каждый недопустимый символ на замену в TextReader, который использует XmlReader. Вот короткий, но полный пример:

using System; 
using System.IO; 
using System.Xml; 

class Test 
{ 
    static void Main() 
    { 
     var text = "<foo>\0</foo>"; 
     var reader = XmlReader.Create(
      new XmlReplacingReader(new StringReader(text), ' ')); 
     while (reader.Read()) 
     { 
      Console.WriteLine(reader.NodeType); 
     } 
    } 
} 

public sealed class XmlReplacingReader : TextReader 
{ 
    private readonly TextReader original; 
    private readonly char replacementChar; 

    public XmlReplacingReader(TextReader original, char replacementChar) 
    { 
     this.original = original; 
     this.replacementChar = replacementChar; 
    } 

    override public int Peek() 
    { 
     int ret = original.Peek(); 
     return MaybeReplace(ret); 
    } 

    override public int Read() 
    { 
     int ret = original.Read(); 
     return MaybeReplace(ret);   
    } 

    override public int Read(char[] buffer, int index, int count) 
    { 
     int ret = original.Read(buffer, index, count); 
     for (int i = 0; i < ret; i++) 
     { 
      buffer[i + index] = MaybeReplace(buffer[i + index]); 
     } 
     return ret; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      original.Dispose(); 
     } 
    } 

    public override void Close() 
    { 
     original.Close(); 
    } 

    private int MaybeReplace(int x) 
    { 
     return x < 0 ? x : MaybeReplace((char) x); 
    } 

    private char MaybeReplace(char c) 
    { 
     return (c >= ' ' || c == '\r' || c == '\n' || c == '\t') ? c : replacementChar; 
    } 
} 

Это зависит от вас возможность создать TextReader для файла, конечно, - что вы можете сделать с File.OpenText, если вы знаете кодировку. Если вам нужно обрабатывать другие кодировки, вам может понадобиться более хитрое решение, но это должно вас начать.

Обратите внимание, что этот подход заменяет недопустимыми символами. Если вы хотите, чтобы удалил их, это становится сложнее и, вероятно, менее эффективно, так как основному методу Read необходимо выяснить, нужно ли ему удалять символы, выполнять удаление, а затем возвращать другое значение. Код был бы намного сложнее - я надеюсь, что вам это не понадобится.

+1

Да, также интересно, почему 'CheckCharacters' не работает для этого случая. Я сделал много других сценариев, где он функционирует правильно, но прямо сейчас, я даже не знаю, что я сделал неправильно. уже некоторое время смотрел ваш фрагмент кода, попытаюсь реализовать это и обновить что-нибудь. –

Смежные вопросы