Как десериализовать XML-документ

Как десериализовать этот XML-документ:

   1020 Nissan Sentra   1010 Toyota Corolla   1111 Honda Accord   

У меня есть это:

 [Serializable()] public class Car { [System.Xml.Serialization.XmlElementAttribute("StockNumber")] public string StockNumber{ get; set; } [System.Xml.Serialization.XmlElementAttribute("Make")] public string Make{ get; set; } [System.Xml.Serialization.XmlElementAttribute("Model")] public string Model{ get; set; } } 

,

 [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlArrayItem(typeof(Car))] public Car[] Car { get; set; } } 

,

 public class CarSerializer { public Cars Deserialize() { Cars[] cars = null; string path = HttpContext.Current.ApplicationInstance.Server.MapPath("~/App_Data/") + "cars.xml"; XmlSerializer serializer = new XmlSerializer(typeof(Cars[])); StreamReader reader = new StreamReader(path); reader.ReadToEnd(); cars = (Cars[])serializer.Deserialize(reader); reader.Close(); return cars; } } 

которые, похоже, не работают 🙁

Вот рабочая версия. Я заменил метки XmlElementAttribute на XmlElement, потому что в xml значения StockNumber, Make и Model являются элементами, а не атрибутами. Также я удалил reader.ReadToEnd (); (эта функция считывает весь stream и возвращает строку, поэтому функция Deserialze () больше не может использовать читателя … позиция была в конце streamа). Я также взял несколько свобод с именованием :).

Вот classы:

 [Serializable()] public class Car { [System.Xml.Serialization.XmlElement("StockNumber")] public string StockNumber { get; set; } [System.Xml.Serialization.XmlElement("Make")] public string Make { get; set; } [System.Xml.Serialization.XmlElement("Model")] public string Model { get; set; } } [Serializable()] [System.Xml.Serialization.XmlRoot("CarCollection")] public class CarCollection { [XmlArray("Cars")] [XmlArrayItem("Car", typeof(Car))] public Car[] Car { get; set; } } 

Функция Deserialize:

 CarCollection cars = null; string path = "cars.xml"; XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); StreamReader reader = new StreamReader(path); cars = (CarCollection)serializer.Deserialize(reader); reader.Close(); 

И слегка измененный xml (мне нужно было добавить новый элемент для обертывания … Net придирчив к десериализации массивов):

     1020 Nissan Sentra   1010 Toyota Corolla   1111 Honda Accord    

Как насчет того, чтобы просто сохранить xml в файл и использовать xsd ?

  1. Запишите файл на диск (я назвал его foo.xml)
  2. Создайте xsd: xsd foo.xml
  3. Создайте C #: xsd foo.xsd /classes

Et voila – и файл кода C #, который должен иметь возможность читать данные через XmlSerializer :

  XmlSerializer ser = new XmlSerializer(typeof(Cars)); Cars cars; using (XmlReader reader = XmlReader.Create(path)) { cars = (Cars) ser.Deserialize(reader); } 

(включая сгенерированный foo.cs в проекте)

У вас есть две возможности.

Метод 1. Инструмент XSD


Предположим, что у вас есть ваш XML-файл в этом месте C:\path\to\xml\file.xml

  1. Командная строка Open Developer
    Вы можете найти его в Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools Или если у вас есть Windows 8, вы можете просто начать вводить команду « Командная строка разработчика» на экране «Пуск»
  2. Измените местоположение на свой файл XML-файла, набрав cd /D "C:\path\to\xml"
  3. Создайте файл XSD из вашего xml-файла, введя xsd file.xml
  4. Создайте classы C # , набрав xsd /c file.xsd

Вот и все! Вы создали classы C # из xml-файла в C:\path\to\xml\file.cs

Метод 2 – Специальная вставка


Требуемая Visual Studio 2012+

  1. Скопировать содержимое вашего XML-файла в буфер обмена
  2. Добавьте к вашему решению новый пустой файл classа ( Shift + Alt + C )
  3. Откройте этот файл и в меню нажмите « Edit > Paste special > Paste XML As Classes
    введите описание изображения здесь

Вот и все!

Применение


Использование этого classа-помощника очень просто:

 using System; using System.IO; using System.Web.Script.Serialization; // Add reference: System.Web.Extensions using System.Xml; using System.Xml.Serialization; namespace Helpers { internal static class ParseHelpers { private static JavaScriptSerializer json; private static JavaScriptSerializer JSON { get { return json ?? (json = new JavaScriptSerializer()); } } public static Stream ToStream(this string @this) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.Write(@this); writer.Flush(); stream.Position = 0; return stream; } public static T ParseXML(this string @this) where T : class { var reader = XmlReader.Create(@this.Trim().ToStream(), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document }); return new XmlSerializer(typeof(T)).Deserialize(reader) as T; } public static T ParseJSON(this string @this) where T : class { return JSON.Deserialize(@this.Trim()); } } } 

Все, что вам нужно сделать сейчас, это:

  public class JSONRoot { public catalog catalog { get; set; } } // ... string xml = File.ReadAllText(@"D:\file.xml"); var catalog1 = xml.ParseXML(); string json = File.ReadAllText(@"D:\file.json"); var catalog2 = json.ParseJSON(); 

Следующий fragment должен сделать трюк (и вы можете игнорировать большинство атрибутов сериализации):

 public class Car { public string StockNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } [XmlRootAttribute("Cars")] public class CarCollection { [XmlElement("Car")] public Car[] Cars { get; set; } } 

 using (TextReader reader = new StreamReader(path)) { XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); return (CarCollection) serializer.Deserialize(reader); } 

Посмотрите, помогает ли это:

 [Serializable()] [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlArrayItem(typeof(Car))] public Car[] Car { get; set; } } 

,

 [Serializable()] public class Car { [System.Xml.Serialization.XmlElement()] public string StockNumber{ get; set; } [System.Xml.Serialization.XmlElement()] public string Make{ get; set; } [System.Xml.Serialization.XmlElement()] public string Model{ get; set; } } 

И если это не так, используйте программу xsd.exe, которая поставляется с визуальной студией, чтобы создать документ схемы на основе этого XML-файла, а затем снова использовать его для создания classа на основе документа схемы.

Я не думаю, что .net «придирчив к десериализации массивов». Первый XML-документ плохо сформирован. Нет корневого элемента, хотя он выглядит так, как есть. Канонический XML-документ имеет корень и не менее 1 элемент (если вообще). В вашем примере:

  <-- well, the root  <-- an element (not a root), it being an array  <-- an element, it being an array item ...    

попробуйте этот блок кода, если ваш .xml-файл был сгенерирован где-то на диске, и если вы использовали List :

 //deserialization XmlSerializer xmlser = new XmlSerializer(typeof(List)); StreamReader srdr = new StreamReader(@"C:\serialize.xml"); List p = (List)xmlser.Deserialize(srdr); srdr.Close();` 

Примечание. C:\serialize.xml – это мой путь к файлу .xml. Вы можете изменить его для своих нужд.

Аналог Кевина хорош, кроме того, что в реальном мире вы часто не можете изменять оригинальный XML в соответствии с вашими потребностями.

Для исходного XML также есть простое решение:

 [XmlRoot("Cars")] public class XmlData { [XmlElement("Car")] public List Cars{ get; set; } } public class Car { public string StockNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } 

И тогда вы можете просто позвонить:

 var ser = new XmlSerializer(typeof(XmlData)); XmlData data = (XmlData)ser.Deserialize(XmlReader.Create(PathToCarsXml)); 

Попробуйте этот универсальный class для сериализации и десериализации XML.

 public class SerializeConfig where T : class { public static void Serialize(string path, T type) { var serializer = new XmlSerializer(type.GetType()); using (var writer = new FileStream(path, FileMode.Create)) { serializer.Serialize(writer, type); } } public static T DeSerialize(string path) { T type; var serializer = new XmlSerializer(typeof(T)); using (var reader = XmlReader.Create(path)) { type = serializer.Deserialize(reader) as T; } return type; } } 

Идея состоит в том, чтобы все уровни обрабатывались для десериализации. Пожалуйста, см. Образец решения, которое разрешило мою аналогичную проблему

    25429 02700701354375000964 F a16af68d4c3e2280e44bd7c2c23f2af6cb1f0e5a28c266ea741608e72b1a5e4224da5b975909cc43c53b6c0f7f1bbf0820269caa3e350dd1812484edc499b279 B1684258EA112C8B5BA51F73CDA9864D1BB98E04F5A78B67A3E539BEF96CCF4D16CFF6B9E04818B50E855E0783BB075309D112CA596BDC49F9738C4BF3AA1FB4 29-09-2015 07:36:59 150929093703RUDZMX4 9967 Bank rejected transaction! RUDZMX       0.00   

Вышеупомянутый XML обрабатывается на двух уровнях

  [XmlType("TRANSACTION_RESPONSE")] public class TransactionResponse { [XmlElement("TRANSACTION")] public BankQueryResponse Response { get; set; } } 

Внутренний уровень

 public class BankQueryResponse { [XmlElement("TRANSACTION_ID")] public string TransactionId { get; set; } [XmlElement("MERCHANT_ACC_NO")] public string MerchantAccNo { get; set; } [XmlElement("TXN_SIGNATURE")] public string TxnSignature { get; set; } [XmlElement("TRAN_DATE")] public DateTime TranDate { get; set; } [XmlElement("TXN_STATUS")] public string TxnStatus { get; set; } [XmlElement("REFUND_DATE")] public DateTime RefundDate { get; set; } [XmlElement("RESPONSE_CODE")] public string ResponseCode { get; set; } [XmlElement("RESPONSE_DESC")] public string ResponseDesc { get; set; } [XmlAttribute("MERCHANT_TRANID")] public string MerchantTranId { get; set; } } 

Тот же способ, которым вам нужен несколько уровней с car as array Посмотрите этот пример для многоуровневой десериализации

Если вы получаете ошибки с помощью xsd.exe для создания xsd-файла, используйте class XmlSchemaInference, как указано в msdn . Вот единичный тест, демонстрирующий:

 using System.Xml; using System.Xml.Schema; [TestMethod] public void GenerateXsdFromXmlTest() { string folder = @"C:\mydir\mydata\xmlToCSharp"; XmlReader reader = XmlReader.Create(folder + "\some_xml.xml"); XmlSchemaSet schemaSet = new XmlSchemaSet(); XmlSchemaInference schema = new XmlSchemaInference(); schemaSet = schema.InferSchema(reader); foreach (XmlSchema s in schemaSet.Schemas()) { XmlWriter xsdFile = new XmlTextWriter(folder + "\some_xsd.xsd", System.Text.Encoding.UTF8); s.Write(xsdFile); xsdFile.Close(); } } // now from the visual studio command line type: xsd some_xsd.xsd /classes 

Вы можете просто изменить один атрибут для вашего автомобиля. Автомобильная собственность от XmlArrayItem до XmlElment. То есть, из

 [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlArrayItem(typeof(Car))] public Car[] Car { get; set; } } 

в

 [System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)] public class Cars { [XmlElement("Car")] public Car[] Car { get; set; } } 

Мое решение:

  1. Используйте Edit > Past Special > Paste XML As Classes чтобы получить class в вашем коде
  2. Попробуйте что-то вроде этого: создайте список этого classа ( List >), а затем используйте XmlSerializer для сериализации этого списка в xml файле.
  3. Теперь вы просто заменяете тело этого файла вашими данными и пытаетесь deserialize его.

Код:

 StreamReader sr = new StreamReader(@"C:\Users\duongngh\Desktop\Newfolder\abc.txt"); XmlSerializer xml = new XmlSerializer(typeof(Class1[])); var a = xml.Deserialize(sr); sr.Close(); 

ПРИМЕЧАНИЕ. Вы должны обратить внимание на имя корня, не меняйте его. Мой - «ArrayOfClass1»

Для начинающих

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

XML из исходного вопроса. Xml находится в файле Class1.xml, path к этому файлу используется в коде для поиска этого xml-файла.

Я использовал ответ от @erymski, чтобы получить эту работу, поэтому создал файл под названием Car.cs и добавил следующее:

 using System.Xml.Serialization; // Added public class Car { public string StockNumber { get; set; } public string Make { get; set; } public string Model { get; set; } } [XmlRootAttribute("Cars")] public class CarCollection { [XmlElement("Car")] public Car[] Cars { get; set; } } 

Другой бит кода, предоставленный @erymski …

 using (TextReader reader = new StreamReader(path)) { XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); return (CarCollection) serializer.Deserialize(reader); } 

… входит в вашу основную программу (Program.cs), в static CarCollection XCar() следующим образом:

 using System; using System.IO; using System.Xml.Serialization; namespace ConsoleApp2 { class Program { public static void Main() { var c = new CarCollection(); c = XCar(); foreach (var k in c.Cars) { Console.WriteLine(k.Make + " " + k.Model + " " + k.StockNumber); } c = null; Console.ReadLine(); } static CarCollection XCar() { using (TextReader reader = new StreamReader(@"C:\Users\SlowLearner\source\repos\ConsoleApp2\ConsoleApp2\Class1.xml")) { XmlSerializer serializer = new XmlSerializer(typeof(CarCollection)); return (CarCollection)serializer.Deserialize(reader); } } } } 

Надеюсь, поможет 🙂

Как создать универсальный class для десериализации XML-документа

 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Generic class to load any xml into a class // used like this ... // YourClassTypeHere InfoList = LoadXMLFileIntoClass(xmlFile); using System.IO; using System.Xml.Serialization; public static T LoadXMLFileIntoClass(string xmlFile) { T returnThis; XmlSerializer serializer = new XmlSerializer(typeof(T)); if (!FileAndIO.FileExists(xmlFile)) { Console.WriteLine("FileDoesNotExistError {0}", xmlFile); } returnThis = (T)serializer.Deserialize(new StreamReader(xmlFile)); return (T)returnThis; } 

Эта часть может быть или не понадобиться. Откройте XML-документ в Visual Studio, щелкните правой кнопкой мыши по XML, выберите свойства. Затем выберите файл схемы.

  • Можете ли вы указать формат для XmlSerialization datetime?
  • Сериализация списков classов для XML
  • Управление несколькими версиями сериализованных объектов Java
  • Обратный (проанализировать вывод) массива Array.toString (int )
  • XML-сериализация свойства интерфейса
  • Переносимость двоичной сериализации типа double / float в C ++
  • Как работает сериализация Java и когда она должна использоваться вместо какой-либо другой техники сохранения?
  • Каков наилучший способ преобразования объекта java в xml с открытым исходным кодом apis
  • Как использовать Gson API Google для десериализации JSON правильно?
  • Сериализация Java с несериализуемыми частями
  • Серийный список JSON <KeyValuePair >
  • Давайте будем гением компьютера.