2009-11-16 17 views
7

मैं किसी ऑब्जेक्ट को XML पर क्रमबद्ध करने के लिए DataContractSerializer का उपयोग कर रहा हूं। मुख्य वस्तु नामस्थान "http://personaltrading.test.com/" के साथ सुरक्षा होल्डिंग है और इसमें नाम की एक संपत्ति है जो नामस्थान "http://core.test.com" नाम वाली कक्षा है। जब मैं इसे एक्सएमएल में क्रमबद्ध करता हूं तो मुझे निम्न मिलता है:एकाधिक नामस्थानों के साथ DataContractSerializer

<ArrayOfSecurityHolding xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://personaltrading.test.com/"> 
    <SecurityHolding> 
    <Amount xmlns:d3p1="http://core.test.com/"> 
     <d3p1:Amount>1.05</d3p1:Amount> 
     <d3p1:CurrencyCode>USD</d3p1:CurrencyCode> 
    </Amount> 
    <BrokerageID>0</BrokerageID> 
    <BrokerageName i:nil="true" /> 
    <RecordID>3681</RecordID> 
    </SecurityHolding></ArrayOfSecurityHolding> 

क्या मैं वैसे भी d3p1 उपसर्ग को नियंत्रित कर सकता हूं? क्या मैं कुछ गलत कर रहा हूं या मुझे कुछ और करना चाहिए?

उत्तर

8

सबसे पहले, नामस्थान उपनाम की पसंद को अच्छी तरह से गठित पार्सर में कोई फर्क नहीं पड़ता।

लेकिन; क्या यह DataContractSerializer होना चाहिए? XmlSerializer के साथ, आप Serialize के अधिभार का उपयोग कर सकते हैं जो XmlSerializerNamespaces स्वीकार करता है। यह आपको उन नामस्थानों और उपनामों को चुनने और चुनने की अनुमति देता है जिनका आप उपयोग करते हैं।

अंततः; DataContractSerializer पूर्ण xml नियंत्रण देने के उद्देश्य से है; यह उसका लक्ष्य नहीं है। यदि आप सख्त एक्सएमएल नियंत्रण चाहते हैं, XmlSerializer एक बेहतर विकल्प है, भले ही यह पुराना हो (और इसमें कुछ बारीकियों/फॉबल्स हैं)।

पूर्ण उदाहरण:

using System; 
using System.Xml.Serialization; 
public class Amount 
{ 
    public const string CoreNamespace = "http://core.test.com/"; 
    [XmlElement("Amount", Namespace=CoreNamespace)] 
    public decimal Value { get; set; } 
    [XmlElement("CurrencyCode", Namespace = CoreNamespace)] 
    public string Currency { get; set; } 
} 
[XmlType("SecurityHolding", Namespace = SecurityHolding.TradingNamespace)] 
public class SecurityHolding 
{ 
    public const string TradingNamespace = "http://personaltrading.test.com/"; 

    [XmlElement("Amount", Namespace = Amount.CoreNamespace)] 
    public Amount Amount { get; set; } 

    public int BrokerageId { get; set; } 
    public string BrokerageName { get; set; } 
    public int RecordId { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     var data = new[] { 
      new SecurityHolding { 
       Amount = new Amount { 
        Value = 1.05M, 
        Currency = "USD" 
       }, 
       BrokerageId = 0, 
       BrokerageName = null, 
       RecordId = 3681 
      } 
     }; 
     var ser = new XmlSerializer(data.GetType(), 
      new XmlRootAttribute("ArrayOfSecurityHolding") { Namespace = SecurityHolding.TradingNamespace}); 
     var ns = new XmlSerializerNamespaces(); 
     ns.Add("foo", Amount.CoreNamespace); 
     ser.Serialize(Console.Out, data, ns); 
    } 
} 

आउटपुट:

<ArrayOfSecurityHolding xmlns:foo="http://core.test.com/" xmlns="http://personaltrading.test.com/"> 
    <SecurityHolding> 
    <foo:Amount> 
     <foo:Amount>1.05</foo:Amount> 
     <foo:CurrencyCode>USD</foo:CurrencyCode> 
    </foo:Amount> 
    <BrokerageId>0</BrokerageId> 
    <RecordId>3681</RecordId> 
    </SecurityHolding> 
</ArrayOfSecurityHolding> 
4

मैं मार्क एक आधार वर्ग में लागू किया जा सकता है कि इस समस्या को हल कर लिया है कुछ अलग ढंग से।

  1. अतिरिक्त डेटा नेमस्पेस को परिभाषित करने के लिए एक नई विशेषता बनाएं जो आप अपने डेटा अनुबंध में उपयोग करेंगे।

    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]  
    public sealed class NamespaceAttribute : Attribute  
    { 
    
        public NamespaceAttribute() 
        { 
        } 
    
        public NamespaceAttribute(string prefix, string uri) 
        { 
         Prefix = prefix; 
         Uri = uri; 
        } 
    
        public string Prefix { get; set; } 
        public string Uri { get; set; } 
    } 
    
  2. अपने डेटा अनुबंधों में विशेषता जोड़ें।

    [DataContract(Name = "SomeObject", Namespace = "http://schemas.domain.com/namespace/")]  
    [Namespace(Prefix = "a", Uri = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]  
    [Namespace(Prefix = "wm", Uri = "http://schemas.datacontract.org/2004/07/System.Windows.Media")]   
    public class SomeObject : SerializableObject   
    {  
    
        private IList<Color> colors; 
    
        [DataMember] 
        [DisplayName("Colors")] 
        public IList<Colors> Colors 
        { 
         get { return colors; } 
         set { colours = value; } 
        } 
    } 
    
  3. फिर अपने Save विधि में, उपयोग प्रतिबिंब गुण हो और फिर उन्हें फ़ाइल पर लिखने में।

    public static void Save(SerializableObject o, string filename) 
    { 
        using (Stream outputStream = new FileStream(filename, FileMode.Create, FileAccess.Write)) 
        { 
         if (outputStream == null) 
          throw new ArgumentNullException("Must have valid output stream"); 
    
         if (outputStream.CanWrite == false) 
          throw new ArgumentException("Cannot write to output stream"); 
    
         object[] attributes; 
         attributes = o.GetType().GetCustomAttributes(typeof(NamespaceAttribute), true);  
    
         XmlWriterSettings writerSettings = new XmlWriterSettings();     
         writerSettings.Indent = true; 
         writerSettings.NewLineOnAttributes = true;     
         using (XmlWriter w = XmlWriter.Create(outputStream, writerSettings)) 
         { 
          DataContractSerializer s = new DataContractSerializer(o.GetType()); 
    
          s.WriteStartObject(w, o); 
          foreach (NamespaceAttribute ns in attributes)      
           w.WriteAttributeString("xmlns", ns.Prefix, null, ns.Uri); 
    
          // content 
          s.WriteObjectContent(w, o); 
          s.WriteEndObject(w); 
         } 
        } 
    } 
    
1

मैं इस समस्या को भी साथ संघर्ष किया है। नीचे दिया गया समाधान इष्टतम आईएमएचओ नहीं है लेकिन यह काम करता है। ऊपर मार्क ग्रेवेल की तरह, मैं XmlSerializer का उपयोग करने का सुझाव देता हूं।

चाल आपकी कक्षा में एक फ़ील्ड जोड़ने के लिए है जो XmlSerializerNamespaces ऑब्जेक्ट देता है। इस क्षेत्र को XmlNamespaceDeclarations विशेषता के साथ सजाया जाना चाहिए। अपनी कक्षा के निर्माता में, नीचे दिए गए उदाहरण में दिखाए गए नामस्थान जोड़ें। नीचे दिए गए xml में ध्यान दें कि रूट तत्व सही ढंग से prefixed और साथ ही कुछ स्ट्रिंग तत्व है।

More info on XmlSerializerNamespaces

Schemas reference

[XmlRoot(Namespace="http://STPMonitor.myDomain.com")] 
public class CFMessage : IQueueMessage<CFQueueItem> 
{ 
    [XmlNamespaceDeclarations] 
    public XmlSerializerNamespaces xmlns; 

    [XmlAttribute("schemaLocation", Namespace=System.Xml.Schema.XmlSchema.InstanceNamespace)] 
    public string schemaLocation = "http://STPMonitor.myDomain.com/schemas/CFMessage.xsd"; 

    [XmlAttribute("type")] 
    public string Type { get; set; } 

    [XmlAttribute("username")] 
    public string UserName { get; set; } 

    [XmlAttribute("somestring", Namespace = "http://someURI.com")] 
    public string SomeString = "Hello World"; 


    public List<CFQueueItem> QueueItems { get; set; } 

    public CFMessage() 
    { 
     xmlns = new XmlSerializerNamespaces(); 
     xmlns.Add("myDomain", "http://STPMonitor.myDomain.com"); 
     xmlns.Add("xyz", "http://someURI.com"); 
    } 
} 


<?xml version="1.0" encoding="utf-16"?> 
<myDomain:CFMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xyz="http://someURI.com" 
xsi:schemaLocation="http://STPMonitor.myDomain.com/schemas/CFMessage.xsd" 
xyz:somestring="Hello World" type="JOIN" username="SJ-3-3008-1" 
xmlns:myDomain="http://STPMonitor.myDomain.com" /> 
0

जोड़े "http: //www.w3।संगठन/2001/एक्सएमएलशेमा "नामस्थान द्वारा:

private static string DataContractSerialize(object obj) 
    { 
     StringWriter sw = new StringWriter(); 

     DataContractSerializer serializer = new DataContractSerializer(obj.GetType()); 

     using (XmlTextWriter xw = new XmlTextWriter(sw)) 
     { 
      //serializer.WriteObject(xw, obj); 
      // 
      // Insert namespace for C# types 
      serializer.WriteStartObject(xw, obj); 
      xw.WriteAttributeString("xmlns", "x", null, "http://www.w3.org/2001/XMLSchema"); 
      serializer.WriteObjectContent(xw, obj); 
      serializer.WriteEndObject(xw); 
     } 

     StringBuilder buffer = sw.GetStringBuilder(); 

     return buffer.ToString(); 
    } 
संबंधित मुद्दे