Как читать из XmlReader, не перемещая его вперед


Эй, ребята, у меня есть такой сценарий:

while (reader.Read())
{
    if (reader.NodeType == XmlNodeType.Element && reader.Name == itemElementName)
    {
        XElement item = null;
        try
        {
            item = XElement.ReadFrom(reader) as XElement;
        }
        catch (XmlException ex)
        {
           //log line number and stuff from XmlException class  
        }
    }
}

В приведенном выше цикле я преобразую определенный узел (itemElementName) в элемент XElement.

Некоторые узлы будут хорошими XML и войдут в XElement, однако некоторые нет.

В CATCH я хотел бы не только поймать стандартный материал XmlException... Я также хотел бы поймать извлечение текущего Xml и строку.

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

Как можно получить "моментальный снимок" содержимого внешнего окна читателя, не вмешиваясь в его положение?

5 8

5 ответов:

На самом деле ReadSubtree вернет считыватель, который "обертывает" исходный считыватель. Таким образом, чтение через новый будет в конечном итоге продвигать оригинальный также. Вы должны рассматривать XmlReader как читатель только вперед, он просто не может вернуться назад. Что касается вашего сценария, то вместо того, чтобы пытаться запомнить часть XML, вы можете попросить читателя указать позицию во входном файле. Просто приведите его к интерфейсу IXmlLineInfo, у него есть методы для возврата строки и позиции. Используя это, вы могли бы вспомнить некоторые начальные положение (перед рассматриваемым элементом), а затем конечное положение ошибки. А затем считайте эту часть из файла ввода в виде обычного текста.

Не используйте никаких операций "чтения" на читателе - как вы обнаружили, это продвигает его. Для проверки содержимого используйте вызовы таких свойств, как reader.HasValue и reader.Value. Посмотрите "XmlReader" в обозревателе объектов, там довольно много свойств, которые вы можете прочитать.

Edit: я не думаю, что есть простой способ просто получить XML, возможно, потому, что текущий узел не может быть допустимым XML сам по себе, например xmlwhitespace, xmltext node или даже XmlAttribute.

Что я сделал, так это прочитал только элемент в XmlDocument, и прочитал его вместо этого. В моем случае мне пришлось конвертировать документ потока в HTML. Я должен был прочитать внутренний элемент, чтобы назначить" стиль " родительскому элементу HTML.

На самом деле, хотя Витек Карас MSFT прав, Елена Купкова опубликовала ловкий маленький читатель закладок XML на https://msdn.microsoft.com/en-us/library/aa302292.aspx . это позволяет вернуться назад с помощью кэширования.

Еще одна идея: прочитайте внешний XML (который продвигает читателя), затем создайте новый читатель из этого XML, который позволяет вам "вернуться назад" и обработать элементы текущего узла.

while (r.ReadToFollowing("ParentNode"))
{
    parentXml = r.ReadOuterXml();

    //since ReadOuterXml() advances the reader to the next parent node, create a new reader to read the remaining elements of the current parent
    XmlReader r2 = XmlReader.Create(new StringReader(parentXml));
    r2.ReadToFollowing("ChildNode");
    childValue = r2.ReadElementContentAsString();
    r2.Close();
}