8

質問: System.Data.DataTable を XML にエクスポートしています。これまでのところ、問題なく動作しています。しかし、私はすべてのデータを属性に入れたいと思っています。これもうまく機能します。しかし、私の問題は、1 つの列ですべての行が NULL の場合、空の属性が書き込まれないことです。したがって、XML を DataTable に読み戻すと、この列がありません...

空であってもすべての列を強制的に書き込むにはどうすればよいですか?
(DataType は必ずしも文字列ではありません)

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
4

5 に答える 5

8

すべての XML 属性には、単一引用符または二重引用符のペアで囲まれた値を割り当てる必要があります。プレーン テキストで NULL 値を表すのに相当するものはありません。空の文字列を表す値のない引用符のペアは、NULL 値と同じではありません。したがって、NULL 属性を表す唯一の方法は、属性を省略することです。

AllowDBNullこれは、 false に設定しDefaultValueて DataColumn に適切なものを割り当てるか、スキーマを含める必要があることを意味します。

Null 値の処理 (ADO.NET)も参照してください。、特に動作を説明するこのセクション:

さらに、DataRow.["columnName"] の null 割り当てのインスタンスには、次の規則が適用されます。

1. 厳密に型指定された適切な null 値である、厳密に型指定された null 列を除くすべてのデフォルトのデフォルト値は DbNull.Value です。

2. XML ファイルへのシリアル化中に Null 値が書き出されることはありません ("xsi:nil" のように)。

3. デフォルトを含むすべての非 null 値は、XML へのシリアル化中に常に書き出されます。これは、null 値 (xsi:nil) が明示的でデフォルト値が暗黙的である XSD/XML セマンティクスとは異なります (XML に存在しない場合、検証パーサーは関連する XSD スキーマから値を取得できます)。DataTable の場合は逆です。null 値は暗黙的であり、既定値は明示的です。

4. XML 入力から読み取られた行の欠落しているすべての列値には、NULL が割り当てられます。NewRow または同様のメソッドを使用して作成された行には、DataColumn のデフォルト値が割り当てられます。

5.IsNull メソッドは、DbNull.Value と INullable.Null の両方に対して true を返します。

于 2012-04-19T16:37:21.323 に答える
2

2 つのポイント:

最初: ExportTable() が例外をスローしました:「DataTable は既に別の DataSet に属しています。」私が実行したとき:

ds.Tables.Add(dtt)

テーブルのローカル コピーを作成して、これを修正しました。

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

これはうまくいきました。

2 つ目: XML を使用して動的 SQL ステートメントを作成する場合、XML エクスポートで NULL 値が省略されている列/フィールドについて心配する必要はありません。XML レコード内の属性を調べて、INSERT または UPDATE ステートメントを作成し、接続コマンドを実行するだけです。これは、DataSet を使用するよりも高速です。

INSERT の場合、1 つの欠点があります。ID 列をインクリメントして主キーを作成すると、ADO.Net DataSet がそれを返します。動的 SQL では、それを取得するために SELECT ステートメントが必要になります。

また、コードを難読化することをお勧めします。

于 2012-10-29T18:23:55.030 に答える
2

DefaultValueを有効なものに設定してみてください

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;
        }
于 2012-04-19T15:53:44.727 に答える
1

少し古いスレッドですが、誰かの役に立つかもしれません:
大きな xml ファイルを頻繁に作成しない場合 (設定のエクスポートなどには問題ありません)、以下の関数を使用できます。それ以外の場合は、cutom xml スキーマを使用することをお勧めします。

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);
}
于 2013-08-11T00:23:12.130 に答える