Мой Kbyte.Ru
Рассылка Kbyte.Ru
Группы на Kbyte.Ru
Партнеры Kbyte.Ru
Сделано руками
Сделано руками
> Статьи - Алексей Немиро -

C# - Работа с XML/XSL

Все статьи / Работа с XML/XSL

Обработка больших XML при помощи XmlReader

Автор: Алексей Немиро | добавлено: 13.08.2012, 21:21 | просмотров: 32839 (37+) | комментариев: 1 | рейтинг: *x1
  В .NET Framework есть несколько основных классов для работы с XML. Большинство классов высокоуровневые и позволяют довольно легко обрабатывать XML-данные. Однако, если данных много, в приложении могут возникнуть проблемы с потреблением оперативной памяти. В этой статье рассмотрен метод чтения большого XML-файла при помощи класса XmlReader на языке C#.

 

Введение

 

Для чтения XML чаще всего используются высокоуровневые классы XmlDocument и XPathDocument. Что не удивительно, ведь ими довольно легко пользоваться. Данные представлены в логичном, понятном виде, можно в любой момент получить любой набор данных в нужно формате. Достигается это за счет того, что xml-данные загружаются в память. Это некритично для сравнительно небольших xml-файлов. Однако когда размер xml-данных доходит до нескольких сотен мегабайт, а то и гигабайт, классы XmlDocument или XPathDocument использовать просто неприлично, а в некоторых случаях и вовсе невозможно, ведь приложение будет требовать объем оперативной памяти равный размеру данных. Именно для таких случаев и предназначен класс XmlReader.

 

В отличие от своих собратьев по пространству имен, класс XmlReader не хранит данные в памяти. Доступ к данным осуществляется последовательно. Но из-за последовательности становится невозможным узнать, что содержит тот или иной xml-элемент, до того, как данные будут прочитаны. Этот недостаток делает класс XmlReader неудобным в использовании и даже может отпугнуть неопытных программистов. Но все не так страшно, как может показаться на первый взгляд.

 

Пример чтения XML

 

Чтобы было понятно, о чем идет речь, приведу простой пример. Предположим, что у нас есть xml-файл с информацией о пользователях Kbyte.Ru:

<kbyte>
 <members>
 <member kuid="1">
  <nickname>Алексей</nickname>
  <firstName>Алексей</firstName>
  <lastName>Немиро</lastName>
 </member>
 <member kuid="288">
  <nickname>Игорь Голов</nickname>
  <firstName>Игорь</firstName>
  <lastName>Голов</lastName>
 </member>
 <member kuid="1858">
  <nickname>[i]Pro</nickname>
  <firstName>Артем</firstName>
  <lastName>Донцов</lastName>
 </member>
 <member kuid="2575">
  <nickname>Shark1</nickname>
  <firstName>Виталий</firstName>
  <lastName />
 </member>
 </members>
</kbyte>

Данные отдельного пользователя находятся в элементе member и содержат: идентификатор пользователя (атрибут kuid), псевдоним (элемент nickname), имя (firstName) и фамилию (lastName).

 

При помощи класса XmlDocument данные каждого пользователя можно получить следующим образом:

XmlDocument xml = new XmlDocument();
xml.Load("XMLFile1.xml");
foreach (XmlNode n in xml.SelectNodes("/kbyte/members/member"))
{
 Console.WriteLine("KUID: {0}", n.Attributes["kuid"].Value);
 Console.WriteLine("Псевдоним: {0}", n.SelectSingleNode("nickname").InnerText);
 Console.WriteLine("Имя: {0}", n.SelectSingleNode("firstName").InnerText);
 Console.WriteLine("Фамилия: {0}", n.SelectSingleNode("lastName").InnerText);
 Console.WriteLine("------------------------------------------");
}

Примечание. Классы XmlDocument и XmlNode принадлежат пространству имен System.Xml. Для их использования необходимо импортировать это пространство в проект.

 

Примечание. Предполагается наличие файла с именем XMLFile1.xml в корневом каталоге приложения, который содержит приведенные выше xml-данные.

 

При использовании класса XPathDocument принципиальных отличий в коде не будет.

XPathDocument xml = new XPathDocument("XMLFile1.xml");
XPathNavigator nav = xml.CreateNavigator();
foreach (XPathNavigator n in nav.Select("/kbyte/members/member"))
{
 Console.WriteLine("KUID: {0}", n.GetAttribute("kuid", ""));
 Console.WriteLine("Псевдоним: {0}", n.SelectSingleNode("nickname").Value);
 Console.WriteLine("Имя: {0}", n.SelectSingleNode("firstName").Value);
 Console.WriteLine("Фамилия: {0}", n.SelectSingleNode("lastName").Value);
 Console.WriteLine("------------------------------------------");
}

Примечание. Классы XPathDocument и XPathNavigator принадлежат пространству имен System.Xml.XPath, которое необходимо импортировать в проект.

 

Класс XPathDocument отличается от XmlDocument в основном тем, что позволяет использовать механизмы языка XPath (XML Path Language). Язык XPath содержит множество встроенных функций для обработки информации, но в рамках данной статьи эта тема рассматриваться не будет.

 

Как видино из вышеприведенных примеров, при использовании классов XmlDocument и XPathDocument доступ к данным осуществляется через коллекцию узлов (node), каждый из которых имеет функции и методы управления содержимым документа. В случае с классом XmlReader все будет менее очевидно, т.к. доступ к данным осуществляется на более низком уровне.

string lastNodeName = "";
using (XmlReader xml = XmlReader.Create("XMLFile1.xml"))
{
 while (xml.Read())
 {
 switch (xml.NodeType)
 {
  case XmlNodeType.Element:
  // нашли элемент member
  if (xml.Name == "member") 
  {
   if (xml.HasAttributes)
   {
   // поиск атрибута kuid
   while (xml.MoveToNextAttribute())
   {
    if (xml.Name == "kuid")
    {
    Console.WriteLine("KUID: {0}", xml.Value);
    break;
    }
   }
   }
  }

  // запоминаем имя найденного элемента
  lastNodeName = xml.Name;

  break;

  case XmlNodeType.Text:
  // нашли текст, смотрим по имени элемента, что это за текст
  if (lastNodeName == "nickname")
  {
   Console.WriteLine("Псевдоним: {0}", xml.Value);
  }
  else if (lastNodeName == "firstName")
  {
   Console.WriteLine("Имя: {0}", xml.Value);
  }
  else if (lastNodeName == "lastName")
  {
   Console.WriteLine("Фамилия: {0}", xml.Value);
  }
  break;

  case XmlNodeType.EndElement:
  // закрывающий элемент
  if (xml.Name == "member")
  {
   Console.WriteLine("------------------------------------------");
  }
  break;
 }
 }
}

XmlReader читает данные последовательно из потока. Свойство NodeType содержит информацию о типе прочитанных данных. При последовательном чтении данных, невозможно сразу перейти в узел /kbyte/members/member. До него должен дойти указатель. Но и после того, как узел будет найден, невозможно узнать, какие данные он содержит, пока указатель не дойдет до этих данных. Код получается сложным для восприятия. И это притом, что в представленном примере структура xml-документа простая. Обработка документов со сложной структурой потребует написания более мудреного кода. Хотя, если хорошенько подумать, даже в самых тяжелых случаях можно упростить задачу. Об этом пойдет речь далее.

 

Работа с XmlReader

 

Класс XmlReader не имеет конструктора. Создать новый экземпляр класса XmlReader можно при помощи метода Create, который принимает либо физический путь или url к xml-документу, либо поток (Stream).

XmlReader xml = XmlReader.Create("XmlFile1.xml");

Для перехода от одного узла к другому предназначена функция Read, которая возвращает либо true, если удалось осуществить переход к узлу, либо, по достижению конца документа, false. Как правило, чтение всего документа производится циклом.

while (xml.Read())
{
 // ...
}

В зависимости от типа узла (NodeType), экземпляр класса XmlReader может содержать дополнительно имя узла (Name) и его текстовое значение (Value).

Console.WriteLine("Тип узла: {0}", xml.NodeType);
Console.WriteLine("Имя узла: {0}", xml.Name);
Console.WriteLine("Значение узла: {0}", xml.Value);

Для проверки наличия данных, предназначены вспомогательные свойства: HasValue – указывает, имеет узел текстовое значение (Value) или нет; HasAttributes – указывает, имеет узел атрибуты или нет; IsEmptyElement – содержит true, если элемент не имеет никаких данных.

 

Если текущий узел содержит атрибуты (HasAttributes = true), то получить их можно при помощи функции MoveToNextAttribute, которая, по аналогии с Read, будет возвращать true, до достижения конца определения элемента. Имя атрибута и значение также будут находиться в свойствах Name и Value.

if (xml.HasAttributes)
{
 while (xml.MoveToNextAttribute())
 {
 Console.WriteLine("Атрибут: {0}", xml.Name);
 Console.WriteLine("Значение: {0}", xml.Value);
 }
}

После считывания атрибутов может потребоваться вернуться назад к элементу, для этого существует метод MoveToElement.

if(xml.MoveToNextAttribute())
{
 Console.WriteLine("Атрибут: {0}", xml.Name);
 xml.MoveToElement();
 Console.WriteLine("Элемент: {0}", xml.Name);
}

Для упрощения обработки документа есть несколько полезных функций. Методы ReadOuterXml и ReadInnerXml позволяют получить фрагменты xml в виде текста, как есть. Так, например, найдя в документе элемент member, при помощи функции ReadOuterXml можно получить его целиком и загрузить в XmlDocument, т.е. обработать данные на более высоком уровне, а не собирать их по крупинкам, как в продемонстрированном ранее примере.

if(xml.NodeType == XmlNodeType.Element)
{
 if (xml.Name == "member")
 {
 XmlDocument xmlDoc = new XmlDocument();
 xmlDoc.LoadXml(xml.ReadOuterXml());
 XmlNode n = xmlDoc.SelectSingleNode("member");
 Console.WriteLine("KUID: {0}", n.Attributes["kuid"].Value);
 Console.WriteLine("Псевдоним: {0}", n.SelectSingleNode("nickname").InnerText);
 Console.WriteLine("Имя: {0}", n.SelectSingleNode("firstName").InnerText);
 Console.WriteLine("Фамилия: {0}", n.SelectSingleNode("lastName").InnerText);
 Console.WriteLine("------------------------------------------");
 }
}

А при желании, можно вообще сделать класс member и создать его экземпляр на основе полученной из xml информации при помощи механизмов десериализации .NET Framework.

[XmlRoot("member")]
public class Member
{

 [XmlAttribute("kuid")]
 public int KUID { get; set; }
 [XmlElement("nickname")]
 public string Nickname { get; set; }
 [XmlElement("firstName")]
 public string FirstName { get; set; }
 [XmlElement("lastName")]
 public string LastName { get; set; }

 public Member() {}

 public Member(string xml)
 {
 LoadXml(xml);
 }

 public void LoadXml(string source)
 {
 XmlSerializer mySerializer = new XmlSerializer(this.GetType());
 using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(source)))
 {
  object obj = mySerializer.Deserialize(ms);
  foreach (PropertyInfo p in obj.GetType().GetProperties())
  {
  PropertyInfo p2 = this.GetType().GetProperty(p.Name);
  if (p2 != null && p2.CanWrite)
  {
   p2.SetValue(this, p.GetValue(obj, null), null);
  }
  }
 }
 }

}

Примечание. Для использования классов xml-сериализации необходимо импортировать в проект пространство имен System.Xml.Serialization. Помимо этого, для работы функции LoadXml может потребоваться импортировать пространства имен System.IO и System.Reflection.

 

Таким образом, обработка данных выходит на еще более высокий уровень.

using (XmlReader xml = XmlReader.Create("XmlFile1.xml"))
{
 while (xml.Read())
 {
 switch (xml.NodeType)
 {
  case XmlNodeType.Element:
  // нашли элемент member
  if (xml.Name == "member")
  {
   // передаем данные в класс Member
   Member m = new Member(xml.ReadOuterXml());
   Console.WriteLine("KUID: {0}", m.KUID);
   Console.WriteLine("Псевдоним: {0}", m.Nickname);
   Console.WriteLine("Имя: {0}", m.FirstName);
   Console.WriteLine("Фамилия: {0}", m.LastName);
   Console.WriteLine("------------------------------------------");
  }
  break;
 }
 }
}

При этом уровень обработки данных повышается не для всего содержимого xml, объем которого может достигать многих гигабайт, а лишь для его небольшого фрагмента. Потребление памяти, да и в целом нагрузка на компьютер, незначительные. А вот что делать, если элемент member будет содержать большие объемы вложенной информации. Например, все сообщения пользователя с форумов Kbyte.Ru?

<kbyte>
 <members>
 <member kuid="1">
  <nickname>Алексей</nickname>
  <firstName>Алексей</firstName>
  <lastName>Немиро</lastName>
  <messages>
  <message id="1">
   <subject>Привет мир!</subject>
   <text>Это тестовое сообщение.</text>
  </message>
  <message id="2">
   <subject>Как работать с XmlReader?</subject>
   <text>Это текст о том, как работать с XmlReader.</text>
  </message>
  </messages>
 </member>
 <member kuid="288">
  <nickname>Игорь Голов</nickname>
  <firstName>Игорь</firstName>
  <lastName>Голов</lastName>
 </member>
 <member kuid="1858">
  <nickname>[i]Pro</nickname>
  <firstName>Артем</firstName>
  <lastName>Донцов</lastName>
  <messages>
  <message id="3">
   <subject>Еще одно сообщение</subject>
   <text>Это текст еще одного тестового сообщения.</text>
  </message>
  </messages>
 </member>
 <member kuid="2575">
  <nickname>Shark1</nickname>
  <firstName>Виталий</firstName>
  <lastName />
  <messages />
 </member>
 </members>
</kbyte>

В этом документе, каждый элемент member содержит один вложенный элемент messages, который в свою очередь может состоять из неограниченного числа элементов message. Если получать все содержимое узла member, то потребление оперативной памяти может быть высоким. Поэтому использование функции ReadOuterXml для этих целей не годится. В подобных случаях нужно разделить логику обработки элементов member и messages. Таким образом, чтобы элемент member содержал только основные данные о пользователе, как и в первых примерах, исключив из него элемент messages. Но и список сообщений никуда не пропадает, он просто будет обработан отдельно, причем ничто не запрещает использовать для этого метод ReadOuterXml.

 

Чтобы исключить объемные фрагменты xml, необходимо записывать в память только то, что нужно. Для этого потребуется создать экземпляр класса XmlWriter. Запись данных проще всего производить в StringBuilder, хотя можно и в поток (Stream). Также потребуется две дополнительных булевых (логических) переменных, одна из которых будет разрешать запись данных в экземпляр XmlWriter, а вторая – информировать об исключении xml элемента.

StringBuilder sb = null;
XmlWriter w = null;
XmlWriterSettings ws = new XmlWriterSettings() { Encoding = Encoding.UTF8 };
bool isMember = false, isSkiped = false;

Пропустить ненужный фрагмент xml можно при помощи метода Skip.

using (XmlReader xml = XmlReader.Create("XmlFile1.xml"))
{
 while (xml.Read())
 {
 switch (xml.NodeType)
 {
  case XmlNodeType.Element:
  // нашли элемент member
  if (xml.Name == "member")
  {
   isMember = true;

   // в памяти есть данные пользователя
   if (sb != null)
   {
   w.Flush();
   w.Close();

   // обрабатываем их
   XmlDocument xmlDoc = new XmlDocument();
   xmlDoc.LoadXml(sb.ToString());
   XmlNode n = xmlDoc.SelectSingleNode("member");
   Console.WriteLine("KUID: {0}", n.Attributes["kuid"].Value);
   Console.WriteLine("Псевдоним: {0}", n.SelectSingleNode("nickname").InnerText);
   Console.WriteLine("Имя: {0}", n.SelectSingleNode("firstName").InnerText);
   Console.WriteLine("Фамилия: {0}", n.SelectSingleNode("lastName").InnerText);
   Console.WriteLine("------------------------------------------");
   }

   // создаем новый XmlWirter, для записи данных пользователя
   sb = new StringBuilder();
   w = XmlWriter.Create(sb, ws);
   w.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
  }
  else if (xml.Name == "messages")
  {
   // пропускаем фрагмент с сообщениями
   xml.Skip();
   // ставим отметку, что фрагмент пропущен
   isSkiped = true;
  }

  // это данные пользователя и не пропущенный фрагмент
  if (isMember && !isSkiped)
  {
   w.WriteStartElement(xml.Name);
   // если есть атрибуты, записываем их
   if (xml.HasAttributes)
   {
   while (xml.MoveToNextAttribute())
   {
    w.WriteAttributeString(xml.Name, xml.Value);
   }
   }
  }

  // убираем отметку о пропущенном фрагменте
  isSkiped = false;
  break;

  case XmlNodeType.Text:
  if (isMember)
  {
   w.WriteString(xml.Value);
  }
  break;

  case XmlNodeType.EndElement:
  if (isMember)
  {
   w.WriteFullEndElement();
  }
  if (xml.Name == "member")
  {
   isMember = false;
  }
  break;

 }
 }
}

По функционалу приведенный листинг ничем не отличается от предыдущих. На выходе также будет получен фрагмент документа, содержащий только элемент member, исключая вложенный элемент messages. Что касается обработки messages, то для этого проще всего сделать отдельный XmlReader при помощи функции ReadSubtree.

else if (xml.Name == "messages")
{
 XmlReader xml2 = xml.ReadSubtree();
 while (xml2.Read())
 {
 switch (xml2.NodeType)
 {
  case XmlNodeType.Element:
  // нашли элемент message
  if (xml2.Name == "message")
  {
   XmlDocument xmlDoc2 = new XmlDocument();
   xmlDoc2.LoadXml(xml2.ReadOuterXml());
   XmlNode n = xmlDoc2.SelectSingleNode("message");
   Console.WriteLine("Сообщение # {0}", n.Attributes["id"].Value);
   Console.WriteLine("Тема: {0}", n.SelectSingleNode("subject").InnerText);
   Console.WriteLine("Текст: {0}", n.SelectSingleNode("text").InnerText);
   Console.WriteLine("------------------------------------------");
  }
  break;
 }
 }

 // пропускаем фрагмент с сообщениями
 xml.Skip();
 // ставим отметку, что фрагмент пропущен
 isSkiped = true;
}

Таким образом, у нас будет отдельно обработан каждый элемент member и каждый связанный с ним message. Это практически никак не отразится на потреблении ресурсов, каким бы большим не был размер xml-файла.

 

По завершению работы с документом, всегда необходимо закрывать поток при помощи метода Close.

 

Примечание. При использовании инструкции using { }, закрытие потока происходит автоматически. Отдельный вызов метода Close может привести к возникновению исключения.

 

Послесловие

 

Логика работы с XmlReader заметно отличается от XmlDocument и XPathDocument. И хотя код может показаться сложным, XmlReader имеет существенные преимущества при обработке xml-данных большого объема. А благодаря последовательности чтения документов, XmlReader идеально подходит для работы с поврежденным потоком данных. Правильно комбинируя XmlReader с другими инструментами работы с XML в .NET Framework можно значительно упростить процесс обработки xml-содержимого.

 

Ниже вы найдете файл, содержащий приведенные в статье примеры. Проект выполнен в виде консольного приложения C# 3.5, хотя код без проблем должен работать, как в ранних версиях .NET Framework, так и в новых.

 

Если у вас возникнут какие-либо вопросы, обращайтесь на форум Kbyte.Ru.

--
Алексей Немиро
12 августа 2012 года

Файлы

XmlReadExample.zip (329 Кб)

 

Ответы на вопросы

+ Добавить в избранное
    ? Помощь
Об авторе

Алексей Немиро

Интернет-деятель. Автор многочисленных статей и переводов статей по программированию и информационным технологиям. Работы Алексея можно найти в популярных печатных изданиях компьютерной тематики. Автор проекта Kbyte.Ru.
Сейчас Алексей занимается профессиональным Web-программированием на базе технологий .NET Framework. Иногда пишет различные программки и компоненты для Windows и Android. В свободное время занимается Web-дизайном, увлекается фото- и видеосъемкой.

См. также:
Профиль автора
Алексей Немиро
Последние комментарии (всего: 1)

Добавлять комментарии могут только зарегистрированные пользователи сайта.
Если у Вас уже есть учетная запись на Kbyte.Ru, пройдите процедуру авторизации OpenID.
Если Вы еще не зарегистрированы на Kbyte.Ru - зарегистрируйтесь.

Есть такая XML:
<?xml version='1.0' encoding='UTF-8'?>
<nvd xmlns:scap-core="http://scap.nist.gov/schema/scap-core/0.1" xmlns:cvss="http://scap.nist.gov/schema/cvss-v2/0.2" xmlns:vuln="http://scap.nist.gov/schema/vulnerability/0.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:patch="http://scap.nist.gov/schema/patch/0.1" xmlns="http://scap.nist.gov/schema/feed/vulnerability/2.0" xmlns:cpe-lang="http://cpe.mitre.org/language/2.0" nvd_xml_version="2.0" ; pub_date="2015-11-10T03:2 3:57" xsi:schemaLocation="http://scap.nist.gov/schema/patch/0.1 [url]http://nvd.nist.gov/schema/patch_0.1.xsd[/url] [url]http://scap.nist.gov/schema/feed/vulnerability/2.0[/url] [url]http://nvd.nist.gov/schema/nvd-cve-feed_2.0.xsd[/url] [url]http://scap.nist.gov/schema/scap-core/0.1[/url] http://nvd.nist.gov/schema/scap-core_0.1.xsd">
<entry id="CVE-2014-2406"&g t;
<vuln:vulnerable-configurat ion id="http://www.nist.gov/">
<cpe-lang:logical-test operator="OR" negate="false">
<cpe-lang:fact-ref name="cpe:/a:oracle:datab ase_server:12.1.0.1"/>
<cpe-lang:fact-ref name="cpe:/a:oracle:datab ase_server:11.2.0.4"/>
<cpe-lang:fact-ref name="cpe:/a:oracle:datab ase_server:11.2.0.3"/>
<cpe-lang:fact-ref name="cpe:/a:oracle:datab ase_server:11.1.0.7"/>
</cpe-lang:logical-test>
</vuln:vulnerable-configura tion>
<vuln:vulnerable-software-l ist>
<vuln:product>cpe:/a:ora cle:database_server:11.2.0.4&l t;/vuln:product>
<vuln:product>cpe:/a:ora cle:database_server:11.2.0.3&l t;/vuln:product>
<vuln:product>cpe:/a:ora cle:database_server:11.1.0.7&l t;/vuln:product>
<vuln:product>cpe:/a:ora cle:database_server:12.1.0.1&l t;/vuln:product>
</vuln:vulnerable-software- list>
<vuln:cve-id>CVE-2014-24 06</vuln:cve-id>
<vuln:published-datetime> ;2014-04-15T21:55:10.743-04:00 </vuln:published-datetime&g t;
<vuln:last-modified-datetim e>2014-04-16T13:22:08.120-0 4:00</vuln:last-modified-da tetime>
<vuln:cvss>
<cvss:base_metrics>
<cvss:score>8.5</cvss :score>
<cvss:access-vector>NETW ORK</cvss:access-vector>
<cvss:access-complexity> MEDIUM</cvss:access-complex ity>
<cvss:authentication>SIN GLE_INSTANCE</cvss:authenti cation>
<cvss:confidentiality-impac t>COMPLETE</cvss:confide ntiality-impact>
<cvss:integrity-impact>C OMPLETE</cvss:integrity-imp act>
<cvss:availability-impact&g t;COMPLETE</cvss:availabili ty-impact>
<cvss:source>http://nvd.nist.gov</cvss:source>
<cvss:generated-on-datetime >2014-04-16T13:22:07.870-04 :00</cvss:generated-on-date time>
</cvss:base_metrics>
</vuln:cvss>
<vuln:references xml:lang="en" reference_type="VENDOR_AD VISORY">
<vuln:source>CONFIRM< /vuln:source>
<vuln:reference href="http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html" xml:lang="en">http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html</vuln:reference>
</vuln:references>
<vuln:summary>Unspecifie d vulnerability in the Core RDBMS component in Oracle Database Server 11.1.0.7, 11.2.0.3, 11.2.0.4, and 12.1.0.1 allows remote authenticated users to affect confidentiality, integrity, and availability via unknown vectors related to "Advisor" and "Select Any Dictionary" privileges.</vuln:summary&g t;
</entry>
</nvd>

Написал код:
class Program
{
static void Main(string[] args)
{
using (XmlReader xml = XmlReader.Create("2.xml&q uot;))
{
while (xml.Read())
{
switch (xml.NodeType)
{
case XmlNodeType.Element:
if (xml.Name == "entry")
{
// передаем данные в класс Member
Member m = new Member(xml.ReadOuterXml());
Console.WriteLine("KUID: {0}", m.ID);
Console.WriteLine("Псевдо ним: {0}", m.published_datetime);

Console.WriteLine("------ ------------------------------ ------");
}
/*else if (xml.Name == "member")
{

}*/
break;
}
}
}
Console.ReadKey();
}
}
[XmlRoot("entry")]
public class Member
{
[XmlAttribute("id")]
public string ID { get; set; }
[XmlElement("vuln:publish ed-datetime")]
public string published_datetime { get; set; }
public Member() { }

public Member(string xml)
{
LoadXml(xml);
}

public void LoadXml(string source)
{
XmlSerializer mySerializer = new XmlSerializer(this.GetType());
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.Get Bytes(source)))
{
object obj = mySerializer.Deserialize(ms); // Ошибка здесь
foreach (PropertyInfo p in obj.GetType().GetProperties())
{
PropertyInfo p2 = this.GetType().GetProperty(p.N ame);
if (p2 != null && p2.CanWrite)
{
p2.SetValue(this, p.GetValue(obj, null), null);
}
}
}
}
}

Но у меня выдаёт программа: В документе XML (1, 2) присутствует ошибка
Здесь ошибка: object obj = mySerializer.Deserialize(ms);
Авторизация
 
OpenID
Зарегистрируйся и получи 10% скидку на добавление своего сайта в каталоги! Подробнее »
Поиск по сайту
Реклама
Счетчики