क्या XML को सूची <T> में शामिल करना संभव है?


155

निम्नलिखित XML को देखते हुए:

<?xml version="1.0"?>
<user_list>
   <user>
      <id>1</id>
      <name>Joe</name>
   </user>
   <user>
      <id>2</id>
      <name>John</name>
   </user>
</user_list>

और निम्न वर्ग:

public class User {
   [XmlElement("id")]
   public Int32 Id { get; set; }

   [XmlElement("name")]
   public String Name { get; set; }
}

क्या यह संभव है XmlSerializerकि xml को एक में डिसेरिएलाइज़ किया जाए List<User>? यदि हां, तो मुझे किस प्रकार की अतिरिक्त विशेषताओं का उपयोग करने की आवश्यकता होगी, या XmlSerializerउदाहरण के निर्माण के लिए मुझे किन अतिरिक्त मापदंडों का उपयोग करने की आवश्यकता है ?

एक सरणी ( User[]) स्वीकार्य होगी, अगर थोड़ा कम बेहतर हो।

जवाबों:


137

आप कर सकते हैं संपुटित तुच्छता सूची:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

[XmlRoot("user_list")]
public class UserList
{
    public UserList() {Items = new List<User>();}
    [XmlElement("user")]
    public List<User> Items {get;set;}
}
public class User
{
    [XmlElement("id")]
    public Int32 Id { get; set; }

    [XmlElement("name")]
    public String Name { get; set; }
}

static class Program
{
    static void Main()
    {
        XmlSerializer ser= new XmlSerializer(typeof(UserList));
        UserList list = new UserList();
        list.Items.Add(new User { Id = 1, Name = "abc"});
        list.Items.Add(new User { Id = 2, Name = "def"});
        list.Items.Add(new User { Id = 3, Name = "ghi"});
        ser.Serialize(Console.Out, list);
    }
}

5
अतिरिक्त स्तर के तत्वों से बचने के लिए [XmlElement ("उपयोगकर्ता")] के साथ अच्छा समाधान। इसे देखते हुए, मैंने यह सुनिश्चित करने के लिए सोचा कि यह एक <user> या <आइटम> नोड उत्सर्जित होगा (यदि आपके पास XmlElement विशेषता नहीं थी), और उसके बाद <user> नोड्स जोड़ें। लेकिन मैंने यह कोशिश की और यह नहीं किया, इस तरह से वही छोड़ना चाहिए जो सवाल चाहता था।
जॉन क्रैग

यदि उपर्युक्त उपयोगकर्ता सूची के तहत मेरे पास दो सूचियाँ हैं, तो क्या होगा? मैंने आपके तरीके की कोशिश की और यह कहता है कि यह पहले से ही XYZ नामक एक सदस्य को एक ही पैरामीटर प्रकारों के साथ परिभाषित करता है
काला जे

मुझे नहीं पता कि यह सही उत्तर के रूप में क्यों चिह्नित है। इसमें सूची को लपेटने के लिए एक वर्ग जोड़ना शामिल है। यह निश्चित रूप से सवाल से बचने की कोशिश कर रहा था।
DDRider62 15

1
@ DDRider62 सवाल "रैपिंग के बिना" नहीं कहता है। ज्यादातर लोग बहुत व्यावहारिक हैं और सिर्फ डेटा बाहर निकालना चाहते हैं। यह उत्तर आपको .Itemsसदस्य के माध्यम से ऐसा करने की अनुमति देता है ।
मार्क ग्रेवेल

50

यदि आप आवश्यक पूंजीकरण से मेल खाने के लिए Userवर्ग को सजाते हैं XmlType:

[XmlType("user")]
public class User
{
   ...
}

फिर ctor XmlRootAttributeपर XmlSerializerवांछित रूट प्रदान कर सकता है और सूची में सीधे पढ़ने की अनुमति देता है <>:

    // e.g. my test to create a file
    using (var writer = new FileStream("users.xml", FileMode.Create))
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<User>),  
            new XmlRootAttribute("user_list"));
        List<User> list = new List<User>();
        list.Add(new User { Id = 1, Name = "Joe" });
        list.Add(new User { Id = 2, Name = "John" });
        list.Add(new User { Id = 3, Name = "June" });
        ser.Serialize(writer, list);
    }

...

    // read file
    List<User> users;
    using (var reader = new StreamReader("users.xml"))
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(List<User>),  
            new XmlRootAttribute("user_list"));
        users = (List<User>)deserializer.Deserialize(reader);
    }

क्रेडिट: के आधार पर जवाब से YK1


11
मेरे विचार में, यह स्पष्ट रूप से प्रश्न का उत्तर है। यह प्रश्न सूची <टी> में मौजूद था। शायद एक को छोड़कर अन्य सभी समाधानों में सूची को समाहित करने के लिए एक रैपिंग क्लास शामिल है, जो निश्चित रूप से पोस्ट किए गए प्रश्न नहीं थे, और प्रश्न के लेखक क्या बचने की कोशिश कर रहा है।
DDRider62

1
इस दृष्टिकोण के साथ, XmlSerializerएक गंभीर मेमोरी लीक से बचने के लिए सांख्यिकीय रूप से कैश और पुन: उपयोग किया जाना चाहिए, विवरण के लिए StreamReader और XmlSerializer का उपयोग करके मेमोरी लीक देखें।
dbc

16

हाँ, यह क्रमबद्ध करेगा और सूची <> का वर्णन करेगा। यदि आपको संदेह है तो बस [XmlArray] विशेषता का उपयोग करें।

[Serializable]
public class A
{
    [XmlArray]
    public List<string> strings;
}

यह Serialize () और Deserialize () दोनों के साथ काम करता है।


16

मुझे लगता है कि मैंने एक बेहतर तरीका ढूंढ लिया है। आपको अपनी कक्षाओं में विशेषताएँ नहीं डालनी हैं। मैंने क्रमांकन और डीराइज़ेशन के लिए दो तरीके बनाए हैं जो सामान्य सूची को पैरामीटर के रूप में लेते हैं।

एक बार देख लो (यह मेरे लिए काम करता है):

private void SerializeParams<T>(XDocument doc, List<T> paramList)
    {
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(paramList.GetType());

        System.Xml.XmlWriter writer = doc.CreateWriter();

        serializer.Serialize(writer, paramList);

        writer.Close();           
    }

private List<T> DeserializeParams<T>(XDocument doc)
    {
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(List<T>));

        System.Xml.XmlReader reader = doc.CreateReader();

        List<T> result = (List<T>)serializer.Deserialize(reader);
        reader.Close();

        return result;
    }

तो आप जो भी सूची चाहते हैं उसे क्रमबद्ध कर सकते हैं! आपको हर बार सूची प्रकार निर्दिष्ट करने की आवश्यकता नहीं है।

        List<AssemblyBO> list = new List<AssemblyBO>();
        list.Add(new AssemblyBO());
        list.Add(new AssemblyBO() { DisplayName = "Try", Identifier = "243242" });
        XDocument doc = new XDocument();
        SerializeParams<T>(doc, list);
        List<AssemblyBO> newList = DeserializeParams<AssemblyBO>(doc);

3
वास्तव में सवाल का जवाब देने के लिए धन्यवाद। मुझे लगता है List<MyClass>कि दस्तावेज़ तत्व का नाम दिया जाना चाहिए ArrayOfMyClass
मैक्स टोरो

8

हां, यह लिस्ट <> को डिसेर्बलाइज करता है। इसे किसी एरे में रखने और लिस्ट में लपेटने / अतिक्रमण करने की आवश्यकता नहीं है।

public class UserHolder
{
    private List<User> users = null;

    public UserHolder()
    {
    }

    [XmlElement("user")]
    public List<User> Users
    {
        get { return users; }
        set { users = value; }
    }
}

देशीकरण कोड,

XmlSerializer xs = new XmlSerializer(typeof(UserHolder));
UserHolder uh = (UserHolder)xs.Deserialize(new StringReader(str));

5

सूची <T> के बारे में निश्चित नहीं है, लेकिन ऐरे निश्चित रूप से सक्षम हैं। और थोड़ा सा जादू फिर से एक सूची में लाना वास्तव में आसान बनाता है।

public class UserHolder {
   [XmlElement("list")]
   public User[] Users { get; set; }

   [XmlIgnore]
   public List<User> UserList { get { return new List<User>(Users); } }
}

2
क्या "धारक" वर्ग के बिना करना संभव है?
डैनियल शेफ़र 20

@ डैनियल, एएफएआईके, नं। आपको कुछ ठोस वस्तु प्रकार में क्रमबद्ध और अस्वाभाविक बनाने की आवश्यकता है। मैं यह नहीं मानता कि एक्सएमएल सीरियलाइज़ेशन मूल रूप से एक सीरीज़ेशन की शुरुआत के रूप में संग्रह कक्षाओं का समर्थन करता है। मैं 100% नहीं जानता कि यद्यपि।
जारेपड़

[XmlElement ("सूची")] इसके बजाय [XmlArray ("सूची")] होना चाहिए। यह एकमात्र तरीका है। Deserialization ने मेरे लिए .NET 4.5 में काम किया
eduardobr

2

कैसा रहेगा

XmlSerializer xs = new XmlSerializer(typeof(user[]));
using (Stream ins = File.Open(@"c:\some.xml", FileMode.Open))
foreach (user o in (user[])xs.Deserialize(ins))
   userList.Add(o);    

विशेष रूप से फैंसी नहीं, लेकिन यह काम करना चाहिए।


2
Stackoverflow में आपका स्वागत है! पोस्ट सटीकता को बेहतर बनाने के लिए नमूना कोड के लिए संक्षिप्त विवरण प्रदान करना हमेशा बेहतर होता है :)
Picrofo Software
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.