.NET एक्सएमएल क्रमांकन गोटेक? [बन्द है]


121

जब मैंने सोचा था कि C # XML क्रमांकन कर रहा हूँ, तो मैंने कुछ गोचरों में भाग लिया है:

  • आप केवल-पढ़ी जा सकने वाली वस्तुओं को क्रमबद्ध नहीं कर सकते (जैसे KeyValuePairs)
  • आप एक सामान्य शब्दकोश को क्रमबद्ध नहीं कर सकते। इसके बजाय, इस आवरण वर्ग ( http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx से ) आज़माएँ :

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

[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{      
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }
}

किसी भी अन्य XML धारावाहिककरण वहाँ से बाहर हो गया?



1
इसके अलावा, आप serialzable शब्दकोश के चार्ल्स Feduke के कार्यान्वयन के लिए एक बार देख ले करना चाहते हैं, वह नियमित रूप से सदस्यों के कारण सदस्यों के बीच सूचना के लिए एक्सएमएल लेखक बनाया डिफ़ॉल्ट serializer से धारावाहिक की जानी चाहिए: deploymentzone.com/2008/09/19/...
शिम्मी वेइटहैंडलर

ऐसा नहीं लगता है कि यह सभी गोचरों को पकड़ लेता है। मैं निर्माण में IEqualityComparer स्थापित कर रहा हूँ, लेकिन यह इस कोड में क्रमबद्ध नहीं है। जानकारी के इस बिट को शामिल करने के लिए इस शब्दकोश का विस्तार करने के बारे में कोई विचार? क्या वह जानकारी टाइप ऑब्जेक्ट के माध्यम से नियंत्रित की जा सकती है?
कोलिनक्रैन

जवाबों:


27

एक अन्य विशाल गोच: जब XML को वेब पेज (ASP.NET) के माध्यम से आउटपुट किया जाता है, तो आप यूनिकोड बाइट-ऑर्डर मार्क को शामिल नहीं करना चाहते हैं । बेशक, BOM का उपयोग करने या न करने के तरीके लगभग समान हैं:

BAD (BOM शामिल):

XmlTextWriter wr = new XmlTextWriter(stream, new System.Text.Encoding.UTF8);

अच्छा:

XmlTextWriter  wr = new XmlTextWriter(stream, new System.Text.UTF8Encoding(false))

आप स्पष्ट रूप से यह इंगित करने के लिए गलत पास कर सकते हैं कि आपको BOM नहीं चाहिए। के बीच स्पष्ट, स्पष्ट अंतर नोटिस Encoding.UTF8और UTF8Encoding

शुरुआत में तीन अतिरिक्त BOM बाइट्स (0xEFBBBF) या (239 187 191) हैं।

संदर्भ: http://chrislaco.com/blog/troublesourcing-common-problems-with-the-xmlserialis/


4
आपकी टिप्पणी और भी उपयोगी होगी यदि आप हमें न केवल बताएंगे, बल्कि क्यों।
नील

1
यह वास्तव में XML क्रमांकन से संबंधित नहीं है ... यह सिर्फ एक XmlTextWriter मुद्दा है
थॉमस लेवेस्क

7
-1: प्रश्न से संबंधित नहीं है, और आपको XmlTextWriter.NET 2.0 या इसके बाद के संस्करण का उपयोग नहीं करना चाहिए ।
जॉन सॉन्डर्स

बहुत उपयोगी संदर्भ लिंक। धन्यवाद।
अनिल वंजारी

21

मैं अभी तक टिप्पणी नहीं कर सकता, इसलिए मैं Dr8k की पोस्ट पर टिप्पणी करूंगा और एक और अवलोकन करूंगा। निजी चर जो सार्वजनिक गटर / सेटर गुण के रूप में उजागर होते हैं, और उन गुणों के माध्यम से क्रमबद्ध / deserialized मिलते हैं। हमने इसे अपनी पुरानी नौकरी के दौरान किया था।

एक बात ध्यान देने योग्य है कि यदि आपके पास उन गुणों में कोई तर्क है, तो तर्क चलाया जाता है, इसलिए कभी-कभी, क्रमबद्धता का क्रम वास्तव में मायने रखता है। सदस्यों को स्पष्ट रूप से आदेश दिया जाता है कि उन्हें कोड में कैसे ऑर्डर किया गया है, लेकिन कोई गारंटी नहीं है, खासकर जब आप किसी अन्य ऑब्जेक्ट को विरासत में प्राप्त कर रहे हों। स्पष्ट रूप से उन्हें आदेश देना पीछे का दर्द है।

मैं इस से अतीत में जला दिया गया है।


17
खेतों के क्रम को स्पष्ट रूप से निर्धारित करने के तरीके खोजते हुए मुझे यह पोस्ट मिली। यह विशेषताओं के साथ किया जाता है: [XmlElementAttribute (आदेश = 1)] सार्वजनिक int फ़ील्ड {...} नकारात्मक पक्ष: इस विशेषता को वर्ग के सभी क्षेत्रों और इसके सभी वंशजों के लिए निर्दिष्ट किया जाना चाहिए! IMO आपको इसे अपनी पोस्ट में जोड़ना चाहिए।
क्रिस्टियन डियाकोन्सु

15

मेमोरी स्ट्रीम से XML स्ट्रिंग में सीरियल करते समय, MemoryStream # GetBuffer () के बजाय MemoryStream # ToArray () का उपयोग करना सुनिश्चित करें या आप जंक वर्णों के साथ समाप्त हो जाएंगे, जो ठीक से deserialize नहीं करेंगे (अतिरिक्त बफर आवंटित होने के कारण)।

http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(VS.80).aspx


3
डॉक्स से सीधे "ध्यान दें कि बफ़र में आवंटित बाइट्स होते हैं जो अप्रयुक्त हो सकते हैं। उदाहरण के लिए, यदि स्ट्रिंग" परीक्षण "मेमोरीस्ट्रीम ऑब्जेक्ट में लिखा गया है, तो गेटबफ़र से लौटे बफर की लंबाई 256 है, 4 नहीं, 252 बाइट्स के साथ। अप्रयुक्त। बफर में केवल डेटा प्राप्त करने के लिए, ToArray विधि का उपयोग करें; हालाँकि, ToArray मेमोरी में डेटा की एक प्रति बनाता है। " msdn.microsoft.com/en-us/library/…
realgt

केवल अब यह देखा। अब बकवास जैसा नहीं लगता।
जॉन सॉन्डर्स

ऐसा पहले कभी नहीं सुना, जो डिबगिंग पर मददगार हो।
रिकी

10

यदि धारावाहिक एक ऐसे सदस्य / संपत्ति का सामना करता है जिसका इंटरफ़ेस अपने प्रकार के रूप में है, तो यह अनुक्रमित नहीं होगा। उदाहरण के लिए, निम्नलिखित XML को क्रमबद्ध नहीं करेगा:

public class ValuePair
{
    public ICompareable Value1 { get; set; }
    public ICompareable Value2 { get; set; }
}

हालांकि यह सिलसिलेवार होगा:

public class ValuePair
{
    public object Value1 { get; set; }
    public object Value2 { get; set; }
}

यदि आपको एक संदेश "सदस्य के लिए हल नहीं प्रकार ..." के साथ एक अपवाद मिलता है, तो यही हो सकता है।
काइल क्राल

9

IEnumerables<T>उपज रिटर्न के माध्यम से उत्पन्न कर रहे हैं कि धारावाहिक नहीं हैं। ऐसा इसलिए है क्योंकि कंपाइलर यील्ड रिटर्न को लागू करने के लिए एक अलग वर्ग बनाता है और उस वर्ग को क्रमबद्धता के रूप में चिह्नित नहीं किया जाता है।


यह 'अन्य' क्रमांकन पर लागू होता है, अर्थात [सीरियल योग्य] विशेषता। यह XmlSerializer के लिए काम नहीं करता है, हालांकि।
टिम रॉबिन्सन


8

आप केवल-पढ़ने के गुणों को क्रमबद्ध नहीं कर सकते। आपके पास एक गेटटर और एक सेटर होना चाहिए, भले ही आप XML को किसी ऑब्जेक्ट में बदलने के लिए डीरिएरलाइजेशन का उपयोग करने का इरादा न करें।

उसी कारण से, आप उन गुणों को अनुक्रमित नहीं कर सकते हैं जो इंटरफेस लौटाते हैं: deserializer को पता नहीं होगा कि किस ठोस वर्ग को तुरंत करना है।


1
वास्तव में आप एक संग्रह संपत्ति को क्रमबद्ध कर सकते हैं, भले ही उसके पास कोई सेटर न हो, लेकिन उसे कंस्ट्रक्टर में इनिशियलाइज़ करना होगा ताकि डिसेरिएलाइज़ेशन इसमें आइटम जोड़ सके
थॉमस लीवेस्क

7

ओह यहाँ एक अच्छा एक है: चूंकि XML क्रमांकन कोड उत्पन्न होता है और एक अलग DLL में रखा जाता है, तो आपको कोई भी सार्थक त्रुटि नहीं मिलती है जब आपके कोड में कोई गलती होती है जो धारावाहिक को तोड़ता है। बस ऐसा कुछ "s3d3fsdf.dll का पता लगाने में असमर्थ"। अच्छा लगा।


11
आप XML "Serializer Generator Tool (Sgen.exe)" का उपयोग करके समय से पहले DLL उत्पन्न कर सकते हैं और अपने आवेदन के साथ तैनात कर सकते हैं।
हुसैनी

6

उस ऑब्जेक्ट को क्रमबद्ध नहीं किया जा सकता है जिसमें एक पैरामीटर रहित अवरोध न हो (बस उसी से काट लिया गया हो)।

और किसी कारण के लिए, निम्नलिखित गुणों से, मूल्य क्रमबद्ध हो जाता है, लेकिन पूर्णनाम नहीं:

    public string FullName { get; set; }
    public double Value { get; set; }

मैं कभी काम करने के चक्कर में नहीं पड़ा, मैंने अभी मूल्य को आंतरिक में बदल दिया है ...


4
पैरामीटर रहित कंस्ट्रक्टर निजी / संरक्षित हो सकता है। यह एक्सएमएल सीरियल के लिए पर्याप्त होगा। FullName वाला मुद्दा वास्तव में अजीब है, ऐसा नहीं होना चाहिए ...
Max Galkin

@ यैकोडर: शायद नहीं, double?लेकिन सिर्फ double?
अबशीशेव

FullName शायद था nullऔर इसलिए धारावाहिक में कोई भी XML उत्पन्न नहीं करेगा
जेसपर

5

एक और बात ध्यान दें: यदि आप "डिफ़ॉल्ट" XML क्रमांकन का उपयोग कर रहे हैं, तो आप निजी / संरक्षित वर्ग के सदस्यों को अनुक्रमित नहीं कर सकते।

लेकिन आप अपनी कक्षा में IXmlSerializable को लागू करने वाले कस्टम XML क्रमांकन तर्क को निर्दिष्ट कर सकते हैं और अपनी ज़रूरत / चाहने वाले किसी भी निजी क्षेत्र को क्रमबद्ध कर सकते हैं।

http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx


4

यदि आपका XML Serialization जेनरेट किया गया असेंबली समान लोड संदर्भ में नहीं है क्योंकि कोड इसका उपयोग करने का प्रयास कर रहा है, तो आप भयानक त्रुटियों में भाग लेंगे:

System.InvalidOperationException: There was an error generating the XML document.
---System.InvalidCastException: Unable to cast object
of type 'MyNamespace.Settings' to type 'MyNamespace.Settings'. at
Microsoft.Xml.Serialization.GeneratedAssembly.
  XmlSerializationWriterSettings.Write3_Settings(Object o)

मेरे लिए इसका कारण लोडफ्रेम संदर्भ का उपयोग करके लोड किया गया एक प्लगइन था जिसमें लोड संदर्भ का उपयोग करने के कई नुकसान हैं। थोड़ा मज़ा ट्रैकिंग कि एक नीचे।



4

XML Serializer द्वारा समर्थित समर्थन के विवरण के लिए " उन्नत XML स्कीमा परिभाषा भाषा विशेषताएँ बाइंडिंग समर्थन " देखें, और जिस तरह से समर्थित XSD सुविधाओं का समर्थन किया गया है उस पर विवरण के लिए।


4

यदि आप किसी सरणी को क्रमबद्ध करने का प्रयास करते हैं List<T>, या IEnumerable<T>जिसमें उप-वर्ग के उदाहरण हैं T, तो आपको उपयोग किए जा रहे सभी उपप्रकारों को सूचीबद्ध करने के लिए XmlArrayItemAttribute का उपयोग करने की आवश्यकता है । अन्यथा आप System.InvalidOperationExceptionक्रमबद्ध होने पर अपवित्र हो जाएंगे ।

यहाँ प्रलेखन से एक पूर्ण उदाहरण का हिस्सा है

public class Group
{  
   /* The XmlArrayItemAttribute allows the XmlSerializer to insert both the base 
      type (Employee) and derived type (Manager) into serialized arrays. */

   [XmlArrayItem(typeof(Manager)), XmlArrayItem(typeof(Employee))]
   public Employee[] Employees;

3

निजी चर / गुण XML क्रमांकन के लिए डिफ़ॉल्ट तंत्र में क्रमबद्ध नहीं हैं, लेकिन बाइनरी क्रमांकन में हैं।


2
हां, यदि आप "डिफ़ॉल्ट" XML क्रमांकन का उपयोग कर रहे हैं। आप अपनी कक्षा में IXmlSerializable को लागू करने वाले कस्टम XML क्रमबद्धता तर्क को निर्दिष्ट कर सकते हैं और अपनी ज़रूरत / चाहने वाले किसी भी निजी क्षेत्र को क्रमबद्ध कर सकते हैं।
मैक्स गालिन 16

1
खैर, यह सच है। मैं इसे संपादित करूंगा। लेकिन उस इंटरफ़ेस को लागू करने से मुझे जो याद है उससे गधे में दर्द होता है।
चार्ल्स ग्राहम

3

गुण के साथ चिह्नित गुण Obsoleteक्रमबद्ध नहीं हैं। मैंने Deprecatedविशेषता के साथ परीक्षण नहीं किया है, लेकिन मुझे लगता है कि यह उसी तरह काम करेगा।


2

मैं वास्तव में इसे समझा नहीं सकता, लेकिन मैंने पाया कि यह क्रमबद्ध नहीं होगा:

[XmlElement("item")]
public myClass[] item
{
    get { return this.privateList.ToArray(); }
}

लेकिन यह होगा:

[XmlElement("item")]
public List<myClass> item
{
    get { return this.privateList; }
}

और यह भी ध्यान देने योग्य है कि यदि आप एक मेमस्ट्रीम में धारावाहिक कर रहे हैं, तो आप इसे उपयोग करने से पहले 0 की तलाश कर सकते हैं।


मुझे लगता है कि यह है क्योंकि यह इसे पुनर्निर्माण नहीं कर सकता। दूसरे उदाहरण में इसे आइटम.एड. () सूची में आइटम जोड़ने के लिए कहा जा सकता है। यह पहली बार में नहीं कर सकता।
इलीटिरिट

18
का प्रयोग करें: [XmlArray ("आइटम"), XmlArrayItem ("myClass", टाइपोफ़ (myClass))
RvdK

1
उसके लिए खुश हो जाओ! हर दिन कुछ सीखें
annakata


2

यदि आपका XSD प्रतिस्थापन समूहों का उपयोग करता है, तो संभावना है कि आप इसे (डी) स्वचालित रूप से अनुक्रमित नहीं कर सकते हैं। इस परिदृश्य को संभालने के लिए आपको अपने खुद के धारावाहिक लिखने होंगे।

उदाहरण के लिए।

<xs:complexType name="MessageType" abstract="true">
    <xs:attributeGroup ref="commonMessageAttributes"/>
</xs:complexType>

<xs:element name="Message" type="MessageType"/>

<xs:element name="Envelope">
    <xs:complexType mixed="false">
        <xs:complexContent mixed="false">
            <xs:element ref="Message" minOccurs="0" maxOccurs="unbounded"/>
        </xs:complexContent>
    </xs:complexType>
</xs:element>

<xs:element name="ExampleMessageA" substitutionGroup="Message">
    <xs:complexType mixed="false">
        <xs:complexContent mixed="false">
                <xs:attribute name="messageCode"/>
        </xs:complexContent>
    </xs:complexType>
</xs:element>

<xs:element name="ExampleMessageB" substitutionGroup="Message">
    <xs:complexType mixed="false">
        <xs:complexContent mixed="false">
                <xs:attribute name="messageCode"/>
        </xs:complexContent>
    </xs:complexType>
</xs:element>

इस उदाहरण में, एक लिफाफे में संदेश हो सकते हैं। हालाँकि, .NET का डिफ़ॉल्ट सीरीज़र संदेश, उदाहरणमेसएजए और मिसमैसेजबी के बीच अंतर नहीं करता है। यह केवल आधार संदेश वर्ग से और उसके लिए क्रमबद्ध करेगा।


0

निजी चर / गुण XML क्रमांकन में क्रमबद्ध नहीं हैं, लेकिन बाइनरी क्रमांकन में हैं।

मेरा मानना ​​है कि यह आपको भी मिलता है यदि आप निजी सदस्यों को सार्वजनिक संपत्तियों के माध्यम से उजागर कर रहे हैं - निजी सदस्यों को अनुक्रमित नहीं किया जाता है, इसलिए सार्वजनिक सदस्य सभी शून्य मानों का संदर्भ दे रहे हैं।


यह सच नहीं है। सार्वजनिक संपत्ति के सेटर को बुलाया जाएगा, और संभवतः, निजी सदस्य को निर्धारित करेगा।
जॉन सॉन्डर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.