2012-04-19 15 views
8

प्रश्न: मैं एक सिस्टम निर्यात कर रहा हूं। डेटा। डेटा को XML में सक्षम। अभी तक यह ठीक काम करता है। लेकिन मैं विशेषताओं में सभी डेटा रखना चाहता हूं, जो ठीक काम करता है। लेकिन मेरी समस्या अब, यदि एक कॉलम में, सभी पंक्तियां पूर्ण हैं, तो कोई खाली विशेषता नहीं लिखी जाती है। तो यदि मैं XML को वापस डेटाटेबल पर पढ़ता हूं, तो इसमें इस कॉलम की कमी है ...सभी स्तंभों के साथ एक्सएमएल के लिए डेटाटेबल को गुणों के रूप में कैसे निर्यात करें?

मैं खाली होने पर भी सभी कॉलम लिखने के लिए मजबूर कैसे कर सकता हूं?
(डेटाप्रकार नहीं necessarely स्ट्रिंग)

public void ExportTable(string strDirectory, DataTable dtt) 
{ 
    using (System.Data.DataSet ds = new System.Data.DataSet()) { 
     string strTable = dtt.TableName; 

     ds.Tables.Add(dtt); 
     ds.DataSetName = strTable; 

     // Move data to attributes 
     foreach (DataTable dt in ds.Tables) { 

      foreach (DataColumn dc in dt.Columns) { 
       dc.ColumnMapping = MappingType.Attribute; 
      } 

     } 

     System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings(); 
     settings.Indent = true; 
     //settings.Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1") 
     settings.Encoding = System.Text.Encoding.UTF8; 
     settings.CloseOutput = true; 
     settings.CheckCharacters = true; 
     settings.NewLineChars = "\r\n"; 
     // vbCr & vbLf 

     // Write as UTF-8 with indentation 
     using (System.Xml.XmlWriter w = System.Xml.XmlWriter.Create(System.IO.Path.Combine(strDirectory, strTable + ".xml"), settings)) { 

      // Strip out timezone 
      foreach (DataTable dt in ds.Tables) { 

       foreach (DataColumn dc in dt.Columns) { 

        if (object.ReferenceEquals(dc.DataType, typeof(DateTime))) { 
         dc.DateTimeMode = DataSetDateTime.Unspecified; 
        } 

       } 

      } 

      ds.Tables[0].WriteXml(w, XmlWriteMode.IgnoreSchema); 
      w.Flush(); 
      w.Close(); 
     } 
     // w 

    } 
    // ds 

} 
// ExportTable 

VB.NET मूल:

Public Sub ExportTable(strDirectory As String, dtt As DataTable) 
     Using ds As New System.Data.DataSet() 
      Dim strTable As String = dtt.TableName 

      ds.Tables.Add(dtt) 
      ds.DataSetName = strTable 

      ' Move data to attributes 
      For Each dt As DataTable In ds.Tables 

       For Each dc As DataColumn In dt.Columns 
        dc.ColumnMapping = MappingType.Attribute 
       Next dc 

      Next dt 

      Dim settings As New System.Xml.XmlWriterSettings() 
      settings.Indent = True 
      'settings.Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1") 
      settings.Encoding = System.Text.Encoding.UTF8 
      settings.CloseOutput = True 
      settings.CheckCharacters = True 
      settings.NewLineChars = vbCrLf ' vbCr & vbLf 

      ' Write as UTF-8 with indentation 
      Using w As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(System.IO.Path.Combine(strDirectory, strTable & ".xml"), settings) 

       ' Strip out timezone 
       For Each dt As DataTable In ds.Tables 

        For Each dc As DataColumn In dt.Columns 

         If dc.DataType Is GetType(DateTime) Then 
          dc.DateTimeMode = DataSetDateTime.Unspecified 
         End If 

        Next dc 

       Next dt 

       ds.Tables(0).WriteXml(w, XmlWriteMode.IgnoreSchema) 
       w.Flush() 
       w.Close() 
      End Using ' w 

     End Using ' ds 

    End Sub ' ExportTable 
+1

XmlWriteMode.WriteSchema का उपयोग करें। एक स्कीमा शामिल के साथ यह कोई फर्क नहीं पड़ता कि यह शून्य मानों के लिए विशेषताओं को जोड़ नहीं है। – JamieSee

+0

@JamieSee: स्कीमा के बिना अच्छा होगा, क्योंकि परिणाम किसी भी प्रोग्रामिंग भाषा में पढ़ना आसान नहीं होना चाहिए, न कि सिर्फ .NET। –

उत्तर

8

करने के लिए स्तंभ DefaultValue की स्थापना हर XML विशेषता एक मूल्य सौंपा जाना चाहिए की कोशिश करो जो एकल या दोहरे उद्धरण चिह्नों की एक जोड़ी में संलग्न है। एक पूर्ण मूल्य को दर्शाने के लिए सादा पाठ में कोई समकक्ष नहीं है। एक खाली स्ट्रिंग का प्रतिनिधित्व करने के लिए कोई मान के साथ उद्धरण चिह्नों की एक जोड़ी एक पूर्ण मान के समान नहीं है। इसलिए, एक पूर्ण विशेषता का प्रतिनिधित्व करने का एकमात्र तरीका विशेषता को छोड़ना है।

इसका मतलब है कि आपको या तो AllowDBNull को गलत पर सेट करने की आवश्यकता होगी और डेटाकॉलम पर उपयुक्त DefaultValue असाइन करना होगा, या स्कीमा शामिल करना होगा।

इसके अलावा, Handling Null Values (ADO.NET)., विशेष रूप से इस खंड जो व्यवहार बताते देखें:

इसके अलावा, निम्नलिखित नियम DataRow का एक उदाहरण के लिए आवेदन [ "columnName"] अशक्त कार्य:।

1 डिफ़ॉल्ट डिफ़ॉल्ट मान DbNull है। दृढ़ता से टाइप किए गए शून्य कॉलम को छोड़कर सभी के लिए वैल्यू, जहां उचित दृढ़ता से शून्य मान टाइप किया गया है।

2. एक्सएलएल फाइलों (जैसे "xsi: nil") में क्रमिकरण के दौरान शून्य मान कभी नहीं लिखे जाते हैं।

3. डिफ़ॉल्ट सहित सभी गैर-शून्य मान हमेशा एक्सएमएल को क्रमबद्ध करते समय लिखा जाता है। यह एक्सएसडी/एक्सएमएल सेमेन्टिक्स के विपरीत है जहां शून्य मान (xsi: nil) स्पष्ट है और डिफ़ॉल्ट मान अंतर्निहित है (यदि एक्सएमएल में मौजूद नहीं है, तो एक वैध पार्सर इसे एक्सएसडी स्कीमा से प्राप्त कर सकता है)। डेटाटेबल के लिए विपरीत सत्य है: एक शून्य मान निहित है और डिफ़ॉल्ट मान स्पष्ट है।

4. एक्सएमएल इनपुट से पढ़ने वाली पंक्तियों के लिए सभी गायब कॉलम मानों को शून्य आवंटित किया जाता है। न्यूरो या इसी तरह के तरीकों का उपयोग करके बनाए गए पंक्तियों को डेटाकॉलम का डिफ़ॉल्ट मान असाइन किया गया है।

5. Isnull विधि दोनों DbNull.Value और INullable.Null के लिए सच है।

2

कुछ वैध

foreach (DataTable dt in ds.Tables) { 

     foreach (DataColumn dc in dt.Columns) { 
      dc.ColumnMapping = MappingType.Attribute; 
      //If type is DataType string 
      dc.DefaultValue = String.Empty; 
     } 
2

दो अंक:

पहले: ExportTable() एक अपवाद फेंक दिया: "DataTable पहले से ही एक और डेटासेट के अंतर्गत आता है।"जब मैं निष्पादित:

ds.Tables.Add(dtt) 

मैं मेज की स्थानीय प्रतिलिपि बनाकर इस सुधारा:।

Dim dtX As DataTable = dtt.Copy 
ds.Tables.Add(dtX) 
ds.DataSetName = strTable 

यह अच्छी तरह से काम

दूसरा: आप एक बनाने के लिए एक्सएमएल का उपयोग करते हैं गतिशील एसक्यूएल कथन, एक्सएमएल निर्यात में छोड़े गए नल मूल्य के साथ कॉलम/फ़ील्ड के बारे में चिंतित होने की कोई आवश्यकता नहीं है। बस एक्सएमएल रिकॉर्ड में मौजूद विशेषताओं के माध्यम से चलें, INSERT या UPDATE स्टेटमेंट बनाएं और कनेक्शन कमांड निष्पादित करें यह यूएसआई से तेज है एक डेटासेट एनजी।

INSERT के लिए इसमें एक कमी है। यदि प्राथमिक कुंजी पहचान कॉलम को बढ़ाकर बनाई गई है, तो ADO.Net डेटासेट इसे वापस कर देगा। डायनामिक एसक्यूएल को इसे पुनः प्राप्त करने के लिए एक चयन कथन की आवश्यकता होगी।

इसके अलावा, आपके कोड को खराब करना अच्छा विचार होगा।

1

यह थोड़ा पुराने धागा है, लेकिन, शायद यह मदद कर सकता है किसी को:
आप बड़े xml फ़ाइलें अक्सर नहीं लिख रहे हैं, तो आप नीचे दिए गए समारोह का उपयोग कर सकते हैं (यह सेटिंग या कुछ इसी तरह के निर्यात के लिए ठीक है), अन्यथा यह cutom उपयोग करना बेहतर है एक्सएमएल स्कीमा।

private static void addEmptyElementsToXML(DataSet dataSet) 
{ 
    foreach (DataTable dataTable in dataSet.Tables) 
    { 
     foreach (DataRow dataRow in dataTable.Rows) 
     { 
      for (int j = 0; j < dataRow.ItemArray.Length; j++) 
      { 
       if (dataRow.ItemArray[j] == DBNull.Value) 
        dataRow.SetField(j, string.Empty); 
      } 
     } 
    } 
} 

उपयोग:

using(DataTable dTable = ..something..) 
using(DataSet dS = new DataSet()) 
using(XmlTextWriter xmlStream = new XmlTextWriter("FILENAME.XML", Encoding.UTF8)) 
{ 
    //set xml to be formatted so it can be easily red by human 
    xmlStream.Formatting = Formatting.Indented; 
    xmlStream.Indentation = 4; 

    //add table to dataset 
    dS.Tables.Add(dTable); 

    //call the mentioned function so it will set all DBNull values in dataset 
    //to string.Empty 
    addEmptyElementsToXML(dS); 

    //write xml to file 
    xmlStream.WriteStartDocument(); 
    dS.WriteXml(xmlStream); 
} 
0

मैं DataSet.WriteXML का उपयोग कर() एक्सएमएल के लिए अशक्त क्षेत्रों लेखन का एक समाधान के लिए पूरी दुनिया को खोज की है। मैंने पाया कि एक प्रदर्शन अनुकूलित तरीके में निम्नलिखित काम करता है। मैंने आपकी सुविधा के लिए एक फ़ंक्शन बनाया है। निम्नलिखित फ़ंक्शन को कॉल करके और तालिकाओं को प्रतिस्थापित करके एक के बाद एक को अपने डेटासेट टेबल को बदलें।

private DataTable GetNullFilledDataTableForXML(DataTable dtSource) 
{ 
    // Create a target table with same structure as source and fields as strings 
    // We can change the column datatype as long as there is no data loaded 
    DataTable dtTarget = dtSource.Clone(); 
    foreach (DataColumn col in dtTarget.Columns) 
     col.DataType = typeof(string); 

    // Start importing the source into target by ItemArray copying which 
    // is found to be reasonably fast for null operations. VS 2015 is reporting 
    // 500-525 milliseconds for loading 100,000 records x 10 columns 
    // after null conversion in every cell 
    // The speed may be usable in many circumstances. 
    // Machine config: i5 2nd Gen, 8 GB RAM, Windows 7 64bit, VS 2015 Update 1 
    int colCountInTarget = dtTarget.Columns.Count; 
    foreach (DataRow sourceRow in dtSource.Rows) 
    { 
     // Get a new row loaded with data from source row 
     DataRow targetRow = dtTarget.NewRow(); 
     targetRow.ItemArray = sourceRow.ItemArray; 

     // Update DBNull.Values to empty string in the new (target) row 
     // We can safely assign empty string since the target table columns 
     // are all of string type 
     for (int ctr = 0; ctr < colCountInTarget; ctr++) 
      if (targetRow[ctr] == DBNull.Value) 
       targetRow[ctr] = String.Empty; 

     // Now add the null filled row to target datatable 
     dtTarget.Rows.Add(targetRow); 
    } 

    // Return the target datatable 
    return dtTarget; 
} 
संबंधित मुद्दे