xmlns =“…”を取得せずにオブジェクトをXMLにシリアル化する方法


109

XML名前空間を自動的にシリアル化することなく、.NETでオブジェクトをシリアル化する方法はありますか?デフォルトでは、.NETはXSIおよびXSD名前空間を含める必要があると考えているようですが、そこには含めたくありません。

回答:


142

ああ...気にしないで。質問が出された後の検索が常に答えを生み出します。シリアル化されている私のオブジェクトはobjは既に定義されています。空の名前空間が1つだけのXMLSerializerNamespaceをコレクションに追加すると、うまくいきます。

このようなVBでは:

Dim xs As New XmlSerializer(GetType(cEmploymentDetail))
Dim ns As New XmlSerializerNamespaces()
ns.Add("", "")

Dim settings As New XmlWriterSettings()
settings.OmitXmlDeclaration = True

Using ms As New MemoryStream(), _
    sw As XmlWriter = XmlWriter.Create(ms, settings), _
    sr As New StreamReader(ms)
xs.Serialize(sw, obj, ns)
ms.Position = 0
Console.WriteLine(sr.ReadToEnd())
End Using

このようなC#で:

//Create our own namespaces for the output
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

//Add an empty namespace and empty value
ns.Add("", "");

//Create the serializer
XmlSerializer slz = new XmlSerializer(someType);

//Serialize the object with our own namespaces (notice the overload)
slz.Serialize(myXmlTextWriter, someObject, ns);

12
VBでこれを試しましたが、xsi属性とxsd属性は消えましたが、xmlns:q12 =、d3p1:type、xmlns:d3p1などの属性が表示されました。
MiddleKay 2013年

16
私はC#バージョンを試して、xsiとxsdを削除しましたが、すべてのXMLタグ名にq1:のプレフィックスを追加しました。C#の例は不完全であるように見え、myXmlTextWriterを参照しているため、VBの例と同じ方法で初期化する必要があると思います。
redtetrahedron 2013年

1
@redtetrahedron q1がらくたを取り除く方法を見つけましたか?
クラッシュ

q1が空の名前空間として追加された場合、回答stackoverflow.com/questions/31946240/…を参照してください
aniruddha

20

余分なxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"とを取り除きたいxmlns:xsd="http://www.w3.org/2001/XMLSchema"が、独自の名前空間を維持しxmlns="http://schemas.YourCompany.com/YourSchema/"たい場合は、この単純な変更を除いて、上記と同じコードを使用します。

//  Add lib namespace with empty prefix  
ns.Add("", "http://schemas.YourCompany.com/YourSchema/");   

13

名前空間を削除したい場合は、バージョンも削除したい場合があります。検索を保存するために、以下のコードで両方を実行できるように機能を追加しました。

メモリでシリアル化するには大きすぎる非常に大きなxmlファイルを作成しているので、出力ファイルを分割してより小さな「チャンク」でシリアル化しているので、私はそれをジェネリックメソッドでラップしました。

    public static string XmlSerialize<T>(T entity) where T : class
    {
        // removes version
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;

        XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
        using (StringWriter sw = new StringWriter())
        using (XmlWriter writer = XmlWriter.Create(sw, settings))
        {
            // removes namespace
            var xmlns = new XmlSerializerNamespaces();
            xmlns.Add(string.Empty, string.Empty);

            xsSubmit.Serialize(writer, entity, xmlns);
            return sw.ToString(); // Your XML
        }
    }

StringWriterデフォルトではUTF-16エンコーディングに設定されているため、ダウンストリームで逆シリアル化の問題が発生する可能性があります。using (var reader = XmlReader.Create(stream)){ reader.Read(); }コンテンツが実際にはUTF-8で記述されているのに、宣言でUTF-16であると宣言されているため、これは例外をスローします。 System.Xml.XmlException: 'There is no Unicode byte order mark. Cannot switch to Unicode.'
タイラーStandishMan

これを回避して引き続きを使用するにはXmlReadervar streamReader = new StreamReader(stream, System.Text.Encoding.UTF8, true);trueを使用できます。trueを指定すると、BOMが見つかった場合はそれが使用されます。それ以外の場合は、デフォルトが指定されます。
タイラーStandishMan

9

私はこのヘルパークラスを提案します:

public static class Xml
{
    #region Fields

    private static readonly XmlWriterSettings WriterSettings = new XmlWriterSettings {OmitXmlDeclaration = true, Indent = true};
    private static readonly XmlSerializerNamespaces Namespaces = new XmlSerializerNamespaces(new[] {new XmlQualifiedName("", "")});

    #endregion

    #region Methods

    public static string Serialize(object obj)
    {
        if (obj == null)
        {
            return null;
        }

        return DoSerialize(obj);
    }

    private static string DoSerialize(object obj)
    {
        using (var ms = new MemoryStream())
        using (var writer = XmlWriter.Create(ms, WriterSettings))
        {
            var serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj, Namespaces);
            return Encoding.UTF8.GetString(ms.ToArray());
        }
    }

    public static T Deserialize<T>(string data)
        where T : class
    {
        if (string.IsNullOrEmpty(data))
        {
            return null;
        }

        return DoDeserialize<T>(data);
    }

    private static T DoDeserialize<T>(string data) where T : class
    {
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(data)))
        {
            var serializer = new XmlSerializer(typeof (T));
            return (T) serializer.Deserialize(ms);
        }
    }

    #endregion
}

:)


素晴らしい答え:)私はこのラインstream.Position = 0;も追加しました私のソリューションでストリーム全体を返しました..期待どおりに動作しました-すべての減速タグが削除されました
ymz

名前空間引数をシリアライザ呼び出しに追加するだけで、デフォルトの名前空間を削除できました。new XmlSerializerNamespaces(new[] {XmlQualifiedName.Empty})代わりに書くnew XmlSerializerNamespaces(new[] {new XmlQualifiedName("", "")})ことは、私の意見では、それをコード化するための意図的に明確な方法です。
Suncat2000

5

生成されたクラスからxmlにシリアル化するときに(たとえば、xsd.exeが使用されたとき)、各要素の余分なxmlns属性を取り除くことができない場合は、次のようになります。

<manyElementWith xmlns="urn:names:specification:schema:xsd:one" />

それから私はあなたのために私のために働いたもの(以前の答えと私がここで見つけものの混合)を共有します

次のように、すべての異なるxmlnsを明示的に設定します。

Dim xmlns = New XmlSerializerNamespaces()
xmlns.Add("one", "urn:names:specification:schema:xsd:one")
xmlns.Add("two",  "urn:names:specification:schema:xsd:two")
xmlns.Add("three",  "urn:names:specification:schema:xsd:three")

それをシリアライズに渡します

serializer.Serialize(writer, object, xmlns);

ルート要素で3つの名前空間が宣言され、それに応じてプレフィックスが付けられる他の要素で生成する必要はなくなります。

<root xmlns:one="urn:names:specification:schema:xsd:one" ... />
   <one:Element />
   <two:ElementFromAnotherNameSpace /> ...

0
        XmlWriterSettings settings = new XmlWriterSettings
        {
            OmitXmlDeclaration = true
        };

        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");

        StringBuilder sb = new StringBuilder();

        XmlSerializer xs = new XmlSerializer(typeof(BankingDetails));

        using (XmlWriter xw = XmlWriter.Create(sb, settings))
        {
            xs.Serialize(xw, model, ns);
            xw.Flush();
            return sb.ToString();
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.