Есть ли возможность клонирования xmlTextReader (или многопроходного чтения)?

В настоящее время мне нужно исправить существующее приложение, чтобы использовать что-то другое, кроме DOM-интерфейса libxml2, потому что оказывается, что он передает XML-файлы настолько большого размера, что их невозможно загрузить в память.

Я переписал загрузку данных с итерации по дереву DOM на использование xmlTextReader для большая часть теперь без особых проблем. (Я использую xmlNewTextReaderFilename для открытия локального файла.)

Однако оказывается, что поддерево, в котором находятся большие данные, должно быть прочитано не по порядку, а я должен собрать некоторые (небольшое количество) данных перед другими. (И проблема как раз в том, что именно это поддерево содержит большой объем данных, поэтому загружать в память только это поддерево тоже особого смысла нет.)

Проще всего было бы просто «клонировать»/«копировать» мой текущий ридер, читать вперед, а затем вернуться к исходному экземпляру, чтобы продолжить чтение там. (Кажется, я не первый... Тут даже что-то реализовано на стороне C#: XML Reader с закладками.)

Однако, похоже, нет никакого способа «скопировать» состояние xmlTextReader.

Если я не могу перечитать часть файла, я также могу перечитать весь файл, что, хотя и расточительно, здесь было бы нормально, но я все же нужно будет помнить, где я был заранее?

Может быть, есть простой способ запомнить для xmlTextReader, где он находится в текущем документе, чтобы я мог позже снова найти эту позицию при чтении документа/файла во второй раз?

Вот пример проблемы:

<root>
  <cat1>
    <data attrib="x1">
      ... here goes up to one GB in stuff ...
    </data>
    <data attrib="y2"> <!-- <<< Want to remember this position without having to re-read the stuff before -->
      ... even more stuff ...
    </data>
    <data attrib="z3">
       <!-- I need (part of) the data here to meaningfully interpret the data in [y2] that 
            came before. The best approach would seem to first skip all that data
            and then start back there at <data attrib="y2"> ... not having to re-read
            the whole [x1] data would be a big plus! -->
    </data>
  </cat1>
  ...
</root>

person Martin Ba    schedule 25.03.2013    source источник


Ответы (1)


Я хотел бы дать обходной ответ из того, что я узнал в списке рассылки XML :

Нет простого способа «клонировать» состояние xmlReader, однако то, что должно быть возможным и довольно простым, — это подсчет чтений, сделанных в документе.

То есть, чтобы прочитать документ с помощью xmlReader, вам, вероятно, придется вызвать следующее:

// looping ...
status = ::xmlTextReaderRead(pReader);

При условии, что вы сделаете это структурированным образом (например, я написал небольшой класс-оболочку, который инкапсулирует мой шаблон использования для xmlReader), добавить счетчик будет относительно легко:

// looping ...
status = ::xmlTextReaderRead(pReader);
if (1 == status) { // success
  ++m_ReadCounter;
}

Для повторного чтения документа (достигнув определенной позиции) вы просто вызываете xmlTextReaderRead несколько m_ReadCounter раз, отбрасывая результаты, пока не достигнете позиции, с которой вы хотите начать снова.

Да, вам придется повторно проанализировать весь документ, но этого может быть достаточно быстро. (И на самом деле может быть лучше/быстрее, чем кэширование очень большой части документа.)

person Martin Ba    schedule 04.04.2013