سؤال

كيف يمكنني إلغاء تسلسل هذا مستند XML:

<?xml version="1.0" encoding="utf-8"?>
<Cars>
  <Car>
    <StockNumber>1020</StockNumber>
    <Make>Nissan</Make>
    <Model>Sentra</Model>
  </Car>
  <Car>
    <StockNumber>1010</StockNumber>
    <Make>Toyota</Make>
    <Model>Corolla</Model>
  </Car>
  <Car>
    <StockNumber>1111</StockNumber>
    <Make>Honda</Make>
    <Model>Accord</Model>
  </Car>
</Cars>

لدي هذا:

[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 لأنه في أكس للStockNumber، جعل والقيم نموذج عناصر، وليس الصفات. كما أزلت reader.ReadToEnd ()؛ (أي يقرأ تيار كامل والعوائد سلسلة، وبالتالي فإن وظيفة Deserialze () لا يمكن استخدام القارئ بعد الآن ... وكان الموقف في نهاية تيار). كما أخذت بعض الحريات مع التسمية:)

.

وهنا هي فئات هي:

[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; }
}

وظيفة إلغاء تسلسل:

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();

وفي أكس أنب قليلا (أنا في حاجة لإضافة عنصر جديد إلى التفاف <سيارات> ... الصافية هي من الصعب إرضاءه حول صفائف deserializing):

<?xml version="1.0" encoding="utf-8"?>
<CarCollection>
<Cars>
  <Car>
    <StockNumber>1020</StockNumber>
    <Make>Nissan</Make>
    <Model>Sentra</Model>
  </Car>
  <Car>
    <StockNumber>1010</StockNumber>
    <Make>Toyota</Make>
    <Model>Corolla</Model>
  </Car>
  <Car>
    <StockNumber>1111</StockNumber>
    <Make>Honda</Make>
    <Model>Accord</Model>
  </Car>
</Cars>
</CarCollection>

نصائح أخرى

ما رأيك أن حفظ xml إلى ملف ، واستخدام xsd لتوليد C# الطبقات ؟

  1. كتابة الملفات إلى القرص (سميتها foo.xml)
  2. توليد xsd: xsd foo.xml
  3. توليد C#: xsd foo.xsd /classes

وآخرون فويلا - و C# رمز الملف ينبغي أن تكون قادرة على قراءة البيانات عن طريق XmlSerializer:

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

(تشمل إنشاء فو.cs في المشروع)

لديك اثنين من الاحتمالات.

الطريقة 1. XSD أداة


لنفترض أن لديك ملف XML الخاص بك في هذا الموقع C:\path\to\xml\file.xml

  1. فتح المطور موجه الأوامر
    يمكنك العثور عليه في Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools أو إذا كان لديك ويندوز 8 فقط ابدأ الكتابة المطور موجه الأوامر في شاشة البدء
  2. تغيير موقع ملف XML دليل بكتابة cd /D "C:\path\to\xml"
  3. إنشاء ملف XSD من ملف xml الخاص بك عن طريق كتابة xsd file.xml
  4. إنشاء C# الطبقات عن طريق كتابة xsd /c file.xsd

وهذا كل شيء!كنت قد ولدت C# الطبقات من ملف xml في C:\path\to\xml\file.cs

الأسلوب 2 - لصق خاص


مطلوب Visual Studio 2012+

  1. نسخ محتوى ملف XML الخاص بك إلى الحافظة
  2. إضافة إلى الحل الخاص بك جديدة فارغة ملف فئة (التحول+Alt+ج)
  3. فتح هذا الملف في القائمة انقر فوق Edit > Paste special > Paste XML As Classes
    enter image description here

وهذا كل شيء!

الاستخدام


استخدام بسيط جدا مع هذه الفئة المساعد:

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<T>(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<T>(this string @this) where T : class
        {
            return JSON.Deserialize<T>(@this.Trim());
        }
    }
}

كل ما عليك القيام به الآن هو:

    public class JSONRoot
    {
        public catalog catalog { get; set; }
    }
    // ...

    string xml = File.ReadAllText(@"D:\file.xml");
    var catalog1 = xml.ParseXML<catalog>();

    string json = File.ReadAllText(@"D:\file.json");
    var catalog2 = json.ParseJSON<JSONRoot>();

والمتكررة التالية ينبغي أن تفعل خدعة (ويمكنك تجاهل معظم سمات التسلسل):

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، ومن ثم استخدامها مرة أخرى لإنشاء فئة على أساس وثيقة المخطط.

وأنا لا أعتقد أن صافي هو 'من الصعب إرضاءه حول deserializing المصفوفات. لم يتم تشكيل جيدا مستند XML الأول. لا يوجد أي عنصر الجذر، على الرغم من أنه يبدو وكأنه هناك. وثيقة أكس الكنسي لديها جذور ولا يقل عن 1 عنصر (على كل حال). في المثال الخاص بك:

<Root> <-- well, the root
  <Cars> <-- an element (not a root), it being an array
    <Car> <-- an element, it being an array item
    ...
    </Car>
  </Cars>
</Root>

ومحاولة هذه الكتلة من التعليمات البرمجية إذا تم إنشاء ملف. xml الخاص بك في مكان ما في القرص وإذا كنت قد استخدمت List<T>:

//deserialization

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

ملحوظة: C:\serialize.xml هو طريقي ملف. xml ل. يمكنك تغييره لاحتياجاتك.

وANSER كيفن هو جيد، وبصرف النظر عن حقيقة أنه في العالم الحقيقي، وكنت في كثير من الأحيان غير قادرة على تغيير XML الأصلي لتناسب احتياجاتك.

وهناك حل بسيط لXML الأصلي، وأيضا:

[XmlRoot("Cars")]
public class XmlData
{
    [XmlElement("Car")]
    public List<Car> 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));

وهذه محاولة الفئة عام ل XML التسلسل وإلغاء التسلسل.

public class SerializeConfig<T> 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;
    }
}

تحليل للمبتدئين

ولقد وجدت الإجابات هنا أن تكون مفيدة جدا، وهذا قلت لا يزال يكافح (قليلا) للحصول على هذا العمل. لذا، في حالة أنه يساعد شخص ما سوف تحدد الحل العمل:

و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);
            }
        }
    }
}

ونأمل أن يساعد: -)

والفكرة هي أن يتم التعامل مع كل مستوى لإلغاء التسلسل يرجى الاطلاع على حل عينة التي حلت لي مشكلة مشابهة

<?xml version="1.0" ?> 
 <TRANSACTION_RESPONSE>
    <TRANSACTION>
        <TRANSACTION_ID>25429</TRANSACTION_ID> 
        <MERCHANT_ACC_NO>02700701354375000964</MERCHANT_ACC_NO> 
        <TXN_STATUS>F</TXN_STATUS> 
        <TXN_SIGNATURE>a16af68d4c3e2280e44bd7c2c23f2af6cb1f0e5a28c266ea741608e72b1a5e4224da5b975909cc43c53b6c0f7f1bbf0820269caa3e350dd1812484edc499b279</TXN_SIGNATURE> 
        <TXN_SIGNATURE2>B1684258EA112C8B5BA51F73CDA9864D1BB98E04F5A78B67A3E539BEF96CCF4D16CFF6B9E04818B50E855E0783BB075309D112CA596BDC49F9738C4BF3AA1FB4</TXN_SIGNATURE2> 
        <TRAN_DATE>29-09-2015 07:36:59</TRAN_DATE> 
        <MERCHANT_TRANID>150929093703RUDZMX4</MERCHANT_TRANID> 
        <RESPONSE_CODE>9967</RESPONSE_CODE> 
        <RESPONSE_DESC>Bank rejected transaction!</RESPONSE_DESC> 
        <CUSTOMER_ID>RUDZMX</CUSTOMER_ID> 
        <AUTH_ID /> 
        <AUTH_DATE /> 
        <CAPTURE_DATE /> 
        <SALES_DATE /> 
        <VOID_REV_DATE /> 
        <REFUND_DATE /> 
        <REFUND_AMOUNT>0.00</REFUND_AMOUNT> 
    </TRANSACTION>
  </TRANSACTION_RESPONSE> 

ويتم التعامل مع 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 الخاص بك، ثم استخدام فئة XmlSchemaInference كما ذكر <لأ href = "http://msdn.microsoft.com/en-us/library/system.xml .schema.xmlschemainference.aspx "يختلط =" نوفولو "> على 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 للحصول على الدرجة في التعليمات البرمجية الخاصة بك
  2. محاولة شيء من هذا القبيل:إنشاء قائمة من تلك الفئة (List<class1> ) ، ثم استخدام 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

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generic class to load any xml into a class
// used like this ...
// YourClassTypeHere InfoList = LoadXMLFileIntoClass<YourClassTypeHere>(xmlFile);

using System.IO;
using System.Xml.Serialization;

public static T LoadXMLFileIntoClass<T>(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، اختر خصائص. ثم اختر ملف المخطط الخاص بك.

async public static Task<JObject> XMLtoNETAsync(XmlDocument ToConvert)
        {
            //Van XML naar JSON
            string jsonText = await Task.Run(() => JsonConvert.SerializeXmlNode(ToConvert));
            //Van JSON naar .net object
            var o = await Task.Run(() => JObject.Parse(jsonText));
            return o;
        }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top