6

C# の XmlSerializer を使用します。

特定のフォルダー内のすべての xml ファイルを逆シリアル化する過程で、XmlException "There is an error in XML document (0, 0)".と InnerException が"There is no Unicode byte order mark. Cannot switch to Unicode".

表示されます。ディレクトリ内のすべての xml は "UTF-16" でエンコードされています。唯一の違いは、一部の xml ファイルには、逆シリアル化中に使用しているオブジェクトのクラスで定義されている要素が欠落していることです。

たとえば、フォルダーに 3 種類の xml があるとします。

file1.xml

<?xml version="1.0" encoding="utf-16"?>
<ns0:PaymentStatus xmlns:ns0="http://my.PaymentStatus">
</ns0:PaymentStatus>

file2.xml

<?xml version="1.0" encoding="utf-16"?>
<ns0:PaymentStatus xmlns:ns0="http://my.PaymentStatus">
<PaymentStatus2 RowNum="1" FeedID="38" />
</ns0:PaymentStatus>

file3.xml

<?xml version="1.0" encoding="utf-16"?>
<ns0:PaymentStatus xmlns:ns0="http://my.PaymentStatus">
<PaymentStatus2 RowNum="1" FeedID="38" />
<PaymentStatus2 RowNum="2" FeedID="39" Amt="26.0000" />
</ns0:PaymentStatus>

上記のxmlを表すクラスがあります:

[XmlTypeAttribute(AnonymousType = true, Namespace = "http://my.PaymentStatus")]
[XmlRootAttribute("PaymentStatus", Namespace = "http://http://my.PaymentStatus", IsNullable = true)]
public class PaymentStatus
{

    private PaymentStatus2[] PaymentStatus2Field;

    [XmlElementAttribute("PaymentStatus2", Namespace = "")]
    public PaymentStatus2[] PaymentStatus2 { get; set; }

    public PaymentStatus()
    {
        PaymentStatus2Field = null;
    }
}

[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "", IsNullable = true)]

public class PaymentStatus2
{

    private byte rowNumField;
    private byte feedIDField;
    private decimal AmtField;
    public PaymentStatus2()
    {
        rowNumField = 0;
        feedIDField = 0;
        AmtField = 0.0M;
    }

    [XmlAttributeAttribute()]
    public byte RowNum { get; set; }

    [XmlAttributeAttribute()]
    public byte FeedID { get; set; }
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public decimal Amt { get; set; }
}

次のスニペットは、私のために逆シリアル化を行います:

foreach (string f in filePaths)
{
  XmlSerializer xsw = new XmlSerializer(typeof(PaymentStatus));
  FileStream fs = new FileStream(f, FileMode.Open);
  PaymentStatus config = (PaymentStatus)xsw.Deserialize(new XmlTextReader(fs));
}

何か不足していますか?UTF-16 を UTF-8 に手動で置き換えようとすると、問題なく動作するように見えるため、エンコード形式を使用する必要があります。

4

3 に答える 3

2

ほとんどencoding="utf-16"の場合、保存されている XML のエンコードとは関係がないため、パーサーがストリームを UTF-16 テキストとして読み取れません。

「encoding」パラメーターを「utf-8」に変更すると、テキストを読み取れるというコメントがあるため、ファイルは実際にはUTF8であると想定しています。選択したエディター (つまり、Visual Studio) でファイルをテキストではなくバイナリとして開くことで、簡単に確認できます。

このような不一致が発生する最も可能性の高い理由は、XML を次のように保存することですwriter.Write(document.OuterXml)(「utf-16」を配置する文字列表現を最初に取得しますが、デフォルトで utf-8 エンコーディングで文字列をストリームに書き込みます)。

考えられる回避策 - コードを記述するのと対称的な方法で XML を読み取る - 文字列として読み取り、文字列から XML をロードする。

適切な修正 - XML が正しく保存されていることを確認してください。

于 2014-08-14T01:51:57.323 に答える
0

これが最善の方法かどうかはわかりませんが、入力ストリームに BOM が含まれていない場合は、さまざまなエンコーディングを処理するために XDocument を使用するだけです...たとえば:

public static T DeserializeFromString<T>(String xml) where T : class
    {
        try
        {
            var xDoc = XDocument.Parse(xml);
            using (var xmlReader = xDoc.Root.CreateReader())
            {
                return new XmlSerializer(typeof(T)).Deserialize(xmlReader) as T;
            }
        }
        catch ()
        {
            return default(T);
        }
    }

もちろん、例外をスローバックしたい場合もありますが、コピー元のコードの場合、失敗したかどうか、または失敗した理由を知る必要はありませんでした...そのため、例外を食べました。

于 2015-06-02T21:39:08.457 に答える