Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Чтение XML 
V
    Опции темы
mr.Anderson
  Дата 12.12.2009, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 1
Всего: 128



Возникла следующая проблема. Есть простой XML-файлик следующего вида:
Код

<?xml version="1.0" encoding="utf-8" ?> 
<Root>
  <TestNode>Данные</TestNode> 
  <TestNode2>Данные 2</TestNode2> 
</Root>

Читать пытаюсь следующим кодом:
Код

//XmlReader reader = XmlReader.Create(CurrentFile);  <-- это делается в другой функции, отдельно, т.е. файл открыт постоянно
string result = null;
while (reader.Read())
    if (reader.Name == node)
    {
        result = reader.ReadInnerXml();
        break;
    }
if (result == null)
    throw new Exception(String.Format("Node \"{0}\" not found.", node));
return result;

Но, если я попытаюсь сначала прочитать второй нод (TestNode2), а потом первый (TestNode), я получу свое исключение, что нод не найден. Я проверял, это возникает, по-видимому, потому, что указатель в ридере остается ниже нужного нода. Метод переоткрывать файл каждый раз - это как-то топорно, хоть и работает. Попробовал обойти проблему через файловый поток. Делаю так:
Код

// перезагружаем файловый поток, если требуется открыть другой файл
if ((_fs == null) || (Path.GetFileNameWithoutExtension(_fs.Name) != CurrentFile))
{
    _CloseFiles();
    _fs = new FileStream(_files[CurrentFile], FileMode.Open, FileAccess.Read);
    _xmlReader = XmlReader.Create(_fs);
}
// ищем нужный нод и запоминаем его содержимое
string result = null;
while (_xmlReader.Read())
    if (_xmlReader.Name == node)
    {
        result = _xmlReader.ReadInnerXml();
        break;
    }
_fs.Seek(0, SeekOrigin.Begin); // сдвигаемся обратно к началу файла <-- вот основное, на что я надеялся
// если нод не найден, генерируем исключение
if (result == null)
    throw new Exception(String.Format("Node \"{0}\" not found.", node));
return result;

Казалось бы, все должно быть правильно. В первый раз нод читается нормально (TestNode2 в нашем случае). Однако, после второй попытки чтения вышележащего нода TestNode я получаю исключение времени выполнения, что читаемый файл содержит ошибку в строке 5, позиция 11. Получаю это на строчке 
Код

while (_xmlReader.Read())

Вопрос: в чем проблема? Почему перенос указателя в потоке обратно не сработал, и как в данном случае следует правильно сделать? Задача вообще простая: XML-файл должен быть открыт на протяжении всего времени работы программы, и при запросе выдавать нужный нод оттуда.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
tol05
Дата 12.12.2009, 19:27 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 36
Всего: 170



Цитата(mr.Anderson @  12.12.2009,  17:46 Найти цитируемый пост)
Но, если я попытаюсь сначала прочитать второй нод (TestNode2), а потом первый (TestNode), я получу свое исключение, что нод не найден. Я проверял, это возникает, по-видимому, потому, что указатель в ридере остается ниже нужного нода.

конечно, этот же обычная потоковая модель, с указателем позиции потока и т.п.
Цитата(mr.Anderson @  12.12.2009,  17:46 Найти цитируемый пост)
_fs.Seek(0, SeekOrigin.Begin); // сдвигаемся обратно к началу файла <-- вот основное, на что я надеялся

а этот оператор не находится вне области цикла?

И вообще, почему бы не использовать DOM объект XmlDocument, его метод Load и методы работы с его содержимым, основанные на XPath?
Зачем такой тяжелый код?


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
mr.Anderson
Дата 12.12.2009, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 1
Всего: 128



Цитата
а этот оператор не находится вне области цикла?

Находится, конечно. Мы же должны сбросить указатель после чтения всего файла, разве нет? Зачем внутри-то цикла его перемещать на начало постоянно? Он так цикл никогда и не закончит.

А вообще, да, надо, наверное, XPath использовать... Попробую.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
tol05
Дата 12.12.2009, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 36
Всего: 170



Цитата(mr.Anderson @  12.12.2009,  18:36 Найти цитируемый пост)
Находится, конечно. Мы же должны сбросить указатель после чтения всего файла, разве нет? Зачем внутри-то цикла его перемещать на начало постоянно? Он так цикл никогда и не закончит.

ясно. Т.е. поток мы можем держать бесконечно долго, чем блокировать источник данных (файл)?
Мда.... весьма запутанный код. Что опять же наталкивает на мысль перейти к XmlDocument.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
mr.Anderson
Дата 12.12.2009, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 1
Всего: 128



Странное что-то...
Код

XmlElement item = _doc["Root/" + node];
// если нод не найден, генерируем исключение (пропускать такое нельзя, локализация ведь программистом проводится)
if (item == null)
    throw new Exception(String.Format("Node \"{0}\" not found.", node));                
return item.InnerText;

Цитата("Отладчик")
node = "TestNode2"

Вылетает исключение "нод не найден". Вроде, все так написано. Документ в _doc загружен. Что не так? Почему нод не находит?

Добавлено через 3 минуты и 35 секунд
ЗЫ структура файла такая же, как выше описано.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
diadiavova
Дата 12.12.2009, 21:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 18
Всего: 142



Цитата(mr.Anderson @  12.12.2009,  19:53 Найти цитируемый пост)
Вроде, все так написано. Документ в _doc загружен.

Строку XPath надо передавать методу SelectNodes


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
RWander
Дата 12.12.2009, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 349
Регистрация: 4.5.2006
Где: Russia.Udm.Izhevs k

Репутация: 1
Всего: 6



Посоветовал бы использовать LINQ to XML, код сократится в разы  smile 


--------------------
Microsoft Certified Technology Specialist - ASP.NET Applications
PM MAIL   Вверх
tol05
Дата 12.12.2009, 22:25 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 36
Всего: 170



пример
Код

XmlDocument doc = new XmlDocument();
doc.Load("file.xml");

XmlNode node2 = doc.SelectSingleNode("descendant::TestNode2");

XmlNode node2_1 = doc.GetElementsByTagName("TestNode2")[0];


Цитата(RWander @  12.12.2009,  21:21 Найти цитируемый пост)
Посоветовал бы использовать LINQ to XML, код сократится в разы

да, можно и так

Это сообщение отредактировал(а) tol05 - 12.12.2009, 22:26


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
mr.Anderson
Дата 13.12.2009, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 1
Всего: 128



LINQ использовать не могу, нужно писать на .NET 2.0 в силу некоторых обстоятельств. Разобрался, действительно, надо было просто SelectSingleNode использовать.

Всем спасибо!
tol05, +1 за мысль.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0866 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.