2013-04-04 5 views
11

पर xsi schemalocation को जोड़ने के लिए कैसे मैं XML फ़ाइल का प्रतिनिधित्व करने वाली ऑब्जेक्ट बनाने के लिए XmlSerializer का उपयोग कर रहा हूं और अब मैं अपनी एक्सएमएल फ़ाइल के रूटलेमेंट में एक स्कीमोकेशन जोड़ना चाहता हूं। मैं निम्नलिखितरूट सी # ऑब्जेक्ट XmlSerializer

 XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); 
     System.IO.FileStream fs = new FileStream(@"C:\test.xml", FileMode.Create); 
     TextWriter writer = new StreamWriter(fs, new UTF8Encoding()); 

     XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
     ns.Add("xy","http://www.w3.org/2005/08/addressing"); 
     ns.Add("xlink","http://www.w3.org/1999/xlink"); 
     serializer.Serialize(writer, myObject, ns); 

तरह नामस्थान में जोड़ सकते हैं लेकिन यह कैसे मैं अपने ग # कोड के भीतर मेरी मूल तत्व के लिए एक xsi:schemalocation विशेषता जोड़ सकता हूँ। नेमस्पेस को सरल ns.Add() के साथ जोड़ा गया था। मैं xsd.exe जेनरेट सी # कक्षा के साथ गड़बड़ से बचना चाहता हूं। या क्या मुझे मैन्युअल रूप से जेनरेट की गई सी # कक्षा संपादित करना है और मेरे एक्सएमएल के मूल तत्व में कुछ विशेषता जोड़ना है?

संपादित करें: मैंने ऐसे उदाहरण देखे हैं जहां मुझे अपना सी # मैन्युअल रूप से संपादित करने की आवश्यकता है, लेकिन कोड में ऐसा करने का एक तरीका होना चाहिए !! अगर हम अपने रूट तत्व में नेमस्पेस जोड़ने में सक्षम हैं, तो schemalocations जोड़ने के लिए क्यों संभव नहीं होना चाहिए?

+1

संबंधित या डुप्लिकेट: [XmlSerialization और xsi: SchemaLocation (xsd.exe)] (https://stackoverflow.com/questions/1408336/xmlserialization-and-xsischemalocation-xsd-exe) – dbc

उत्तर

9

के निम्नलिखित XSD मान लेते हैं:

<?xml version="1.0" encoding="utf-8" ?> 
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) --> 
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:element name="elementB"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element name="FirstName" type="xsd:string"/> 
       <xsd:element name="LastName" type="xsd:string"/> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
</xsd:schema> 

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

xsd.exe इस उत्पन्न करता है:

//------------------------------------------------------------------------------ 
// <auto-generated> 
//  This code was generated by a tool. 
//  Runtime Version:4.0.30319.18034 
// 
//  Changes to this file may cause incorrect behavior and will be lost if 
//  the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

using System.Xml.Serialization; 

// 
// This source code was auto-generated by xsd, Version=4.0.30319.1. 
// 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/XMLSchema.xsd")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/XMLSchema.xsd", IsNullable=false)] 
public partial class elementB { 

    private string firstNameField; 

    private string lastNameField; 

    /// <remarks/> 
    public string FirstName { 
     get { 
      return this.firstNameField; 
     } 
     set { 
      this.firstNameField = value; 
     } 
    } 

    /// <remarks/> 
    public string LastName { 
     get { 
      return this.lastNameField; 
     } 
     set { 
      this.lastNameField = value; 
     } 
    } 
} 

"इंजेक्षन" करने के लिए xsi:schemaLocation एक नया वर्ग जोड़ने के लिए, elementA : elementB; सूचना:

  • System.Xml.Serialization.XmlRootAttribute सेटअप
  • schemaLocation संपत्ति सेटअप।

टेस्ट कार्यक्रम:

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

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      elementB b = new elementB(); 
      b.FirstName = "P"; 
      b.LastName = "G"; 

      XmlSerializer ser = new XmlSerializer(typeof(elementB)); 
      StringBuilder sb = new StringBuilder(); 
      using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true })) 
      { 
       ser.Serialize(writer, b); 
      } 
      Console.WriteLine(sb.ToString()); 

      elementA a = new elementA(); 
      a.FirstName = "P"; 
      a.LastName = "G"; 
      a.schemaLocation = "http://tempuri.org/XMLSchema.xsd me"; 
      ser = new XmlSerializer(typeof(elementA)); 
      sb = new StringBuilder(); 
      using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true })) 
      { 
       ser.Serialize(writer, a); 
      } 
      Console.WriteLine(sb.ToString()); 
     } 
    } 
} 

[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/XMLSchema.xsd")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/XMLSchema.xsd", ElementName = "elementB", IsNullable = false)] 
public partial class elementA : elementB 
{ 

    private string torefField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/2001/XMLSchema-instance")] 
    public string schemaLocation 
    { 
     get 
     { 
      return this.torefField; 
     } 
     set 
     { 
      this.torefField = value; 
     } 
    } 
} 

अपेक्षित परिणाम उत्पन्न करता है:

<?xml version="1.0" encoding="utf-16"?> 
<elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/XMLSchema.xsd"> 
    <FirstName>P</FirstName> 
    <LastName>G</LastName> 
</elementB> 
<?xml version="1.0" encoding="utf-16"?> 
<elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd me" xmlns="http://tempuri.org/XMLSchema.xsd"> 
    <FirstName>Petru</FirstName> 
    <LastName>Gardea</LastName> 
</elementB> 

दूसरा तरीका एक कस्टम लेखक पर निर्भर करता है इंजेक्षन करेगा कि आप क्या चाहते हैं, जहाँ भी आप यह चाहते (यह मानते हुए उचित तर्क)।

आप एक कस्टम XmlWriter लागू:

class MyXmlWriter : XmlWriter 
{ 
    XmlWriter _writer; 
    bool _docElement = true; 

    public string SchemaLocation { get; set; } 
    public string NoNamespaceSchemaLocation { get; set; } 

    public MyXmlWriter(XmlWriter writer) 
    { 
     _writer = writer; 
    } 

    (other methods omitted) 

    public override void WriteStartElement(string prefix, string localName, string ns) 
    { 
     _writer.WriteStartElement(prefix, localName, ns); 
     if (_docElement) 
     { 
      if (!string.IsNullOrEmpty(SchemaLocation)) 
      { 
       _writer.WriteAttributeString("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance", SchemaLocation); 
      } 
      if (!string.IsNullOrEmpty(NoNamespaceSchemaLocation)) 
      { 
       _writer.WriteAttributeString("xsi", "noNamesapceSchemaLocation", "http://www.w3.org/2001/XMLSchema-instance", NoNamespaceSchemaLocation); 
      } 
      _docElement = false; 
     } 
    } 

    (other methods omitted) 

} 

एक संशोधित परीक्षण कार्यक्रम:

static void Main(string[] args) 
{ 
    elementB b = new elementB(); 
    b.FirstName = "P"; 
    b.LastName = "G"; 

    XmlSerializer ser = new XmlSerializer(typeof(elementB)); 
    StringBuilder sb = new StringBuilder(); 
    using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true })) 
    { 
     ser.Serialize(writer, b); 
    } 
    Console.WriteLine(sb.ToString()); 

    sb = new StringBuilder(); 

    using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true })) 
    { 
     MyXmlWriter newWriter = new MyXmlWriter(writer) { SchemaLocation = "http://tempuri.org/XMLSchema.xsd me" }; 
     ser.Serialize(newWriter, b); 
    } 
    Console.WriteLine(sb.ToString()); 
} 

परिणाम एक ही है ...

<?xml version="1.0" encoding="utf-16"?> 
<elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/XMLSchema.xsd"> 
    <FirstName>P</FirstName> 
    <LastName>G</LastName> 
</elementB> 
<?xml version="1.0" encoding="utf-16"?> 
<elementB xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd me" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd"> 
    <FirstName>P</FirstName> 
    <LastName>G</LastName> 
</elementB> 
+0

thx आपकी पोस्ट के लिए। अपने स्वयं के स्रोत कोड में रूट क्लास को विस्तारित करना बहुत ही प्रभावशाली दिखता है। मैं कुछ व्यावहारिक अनुभव के बाद वापस रिपोर्ट करूंगा। – Gero

13

XSD.exe आंशिक उत्पन्न करता है कक्षाएं, ताकि आप xsi जैसे स्कीमा स्थान को फ़ील्ड या गुणों के रूप में रखने के लिए अपनी अलग आंशिक कक्षा जोड़ सकें।

तो, @Petru Gardea के नमूने elementB वर्ग को जोड़ने, आप केवल अपनी परियोजना में एक और फ़ाइल बनाएँ और इस आंशिक वर्ग को जोड़ने की आवश्यकता:

public partial class elementB 
{ 
    [XmlAttributeAttribute("schemaLocation", Namespace="http://www.w3.org/2001/XMLSchema-instance")] 
    public string xsiSchemaLocation = "http://www.acme.com/xml/OrderXML-1-0.xsd"; 
} 

एक पकड़ लिया है कि मैं और ऐसा करने में है कि भाग गया है डिफ़ॉल्ट रूप से xsd.exe जेनरेट की गई फाइलों में नामस्थान नहीं जोड़ता है। जब आप अपनी आंशिक कक्षा बनाते हैं, तो यह संभवतः नामस्थान में होगा। चूंकि < डिफ़ॉल्ट नामस्थान> और एक स्पष्ट रूप से परिभाषित नामस्थान मेल नहीं खाता है, आंशिक काम नहीं करेगा। इसलिए, आपको वास्तव में जेनरेट कक्षाओं को अपने नेमस्पेस में प्राप्त करने के लिए xsd.exe पर नेमस्पेस विकल्प का उपयोग करने की आवश्यकता है।

+0

नमस्ते, "xsd.exe पर नेमस्पेस विकल्प का उपयोग करने के लिए वास्तव में जेनरेट कक्षाओं को अपने नेमस्पेस में प्राप्त करने के लिए" क्या मतलब है? –

+1

@CiaranGallagher xsd.exe कमांड लाइन पर, इसका नाम/नामस्थान नाम है: यह उस नामस्थान में जेनरेट की गई कक्षाओं को लपेट देगा – ToddK