Bir nesneyi xmlns = “…” almadan XML'e nasıl serileştirebilirim?


109

XML Ad Alanları otomatik olarak serileştirmeden .NET'te bir nesneyi serileştirmenin bir yolu var mı? Görünüşe göre .NET, varsayılan olarak XSI ve XSD ad alanlarının dahil edilmesi gerektiğine inanıyor, ancak ben onları orada istemiyorum.

Yanıtlar:


142

Ahh ... boşver. Her zaman cevap veren soru sorulduktan sonraki arayıştır. Serileştirilen nesnem objzaten tanımlanmış durumda. Koleksiyona tek bir boş ad alanı içeren bir XMLSerializerNamespace eklemek hile yapar.

VB'de şöyle:

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 # şu şekilde:

//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
Bunu VB'de denedim, xsi ve xsd öznitelikleri kayboldu ancak xmlns: q12 =, d3p1: type ve xmlns: d3p1 gibi öznitelikler belirdi.
MiddleKay

16
C # sürümünü denedim ve xsi ve xsd'yi kaldırdım, ancak istemediğim tüm XML etiket adlarına bir q1: öneki ekledim. Görünüşe göre C # örneği tamamlanmamış, myXmlTextWriter'a başvuruyor ve VB örneğiyle aynı şekilde başlatılması gerektiğini varsayıyorum.
redtetrahedron

1
@redtetrahedron Saçmalıklardan kurtulmanın bir yolunu q1buldunuz mu?
ezmek

Yanıta bakın stackoverflow.com/questions/31946240/…Q1 boş ad alanı olarak eklenirse
aniruddha

20

Fazlalıklardan kurtulmak xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"ve xmlns:xsd="http://www.w3.org/2001/XMLSchema"yine de kendi ad alanınızı korumak istiyorsanız xmlns="http://schemas.YourCompany.com/YourSchema/", bu basit değişiklik dışında yukarıdakiyle aynı kodu kullanırsınız:

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

13

Ad alanını kaldırmak isterseniz sürümü de kaldırmak isteyebilirsiniz, sizi aramadan kurtarmak için bu işlevi ekledim, böylece aşağıdaki kod her ikisini de yapacaktır.

Ayrıca, bellekte serileştirmek için çok büyük olan çok büyük xml dosyaları oluşturduğum için, çıktı dosyamı parçalara ayırdığım ve onu daha küçük "yığınlar" halinde serileştirdiğim için onu genel bir yönteme sardım:

    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
        }
    }

Dikkat edin, StringWritervarsayılan olarak UTF-16 Kodlaması kullanılır ve bu durum aşağı akışta seriyi kaldırma sorunlarına yol açabilir. using (var reader = XmlReader.Create(stream)){ reader.Read(); }Bu bir istisna atar, çünkü bildirim UTF-16 olduğunu belirtirken içerik aslında UTF-8 olarak yazılmıştır. System.Xml.XmlException: 'There is no Unicode byte order mark. Cannot switch to Unicode.'
Tyler StandishMan

Bundan kaçınmak ve hala kullanmak için XmlReaderkullanabileceğiniz var streamReader = new StreamReader(stream, System.Text.Encoding.UTF8, true);, sağladığınız başka varsayılan bulursa BOM kullanacak gerçek.
Tyler StandishMan

9

Bu yardımcı sınıfı öneriyorum:

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
}

:)


harika cevap :) Bu satır akışını da ekledim.Pozisyon = 0; ve
çözümümdeki

Tek başına serileştirici çağrısına ad alanları bağımsız değişkeni eklemek, varsayılan ad alanlarını kaldırmam için çalıştı. new XmlSerializerNamespaces(new[] {XmlQualifiedName.Empty})Bunun yerine yazmak new XmlSerializerNamespaces(new[] {new XmlQualifiedName("", "")}), bence onu kodlamanın daha net bir yolu.
Suncat2000

5

Her öğe için fazladan xmlns özniteliklerinden kurtulamıyorsanız, üretilen sınıflardan xml'ye serileştirirken (örneğin: xsd.exe kullanıldığında), aşağıdaki gibi bir şeye sahip olursunuz:

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

o zaman benim için işe yarayan şeyleri sizinle paylaşırdım (önceki cevapların ve burada bulduklarımın bir karışımı )

tüm farklı xmlns'lerinizi aşağıdaki gibi açıkça ayarlayın:

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")

sonra onu serileştirmeye aktar

serializer.Serialize(writer, object, xmlns);

kök öğede bildirilen üç ad alanına sahip olacaksınız ve buna göre önek eklenecek diğer öğelerde artık üretilmesine gerek kalmayacak

<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();
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.