Как читать из XmlReader, не двигая его вперед - PullRequest
8 голосов
/ 01 июня 2010

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

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, он перемещает читателя вперед.

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

Ответы [ 5 ]

10 голосов
/ 19 июня 2010

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

3 голосов
/ 01 июня 2010

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

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

1 голос
/ 12 сентября 2016

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

1 голос
/ 17 июля 2015

Другая идея: прочитать внешний 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();
}                  
0 голосов
/ 22 января 2015

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

...