Làm cách nào để tuần tự hóa một đối tượng sang XML mà không nhận được xmlns = “…”?


109

Có cách nào để tôi tuần tự hóa một đối tượng trong .NET mà không có Không gian tên XML cũng tự động tuần tự hóa không? Có vẻ như theo mặc định .NET tin rằng không gian tên XSI và XSD nên được bao gồm, nhưng tôi không muốn chúng ở đó.

Câu trả lời:


142

Ahh ... đừng bận tâm. Việc tìm kiếm sau khi câu hỏi được đặt ra luôn mang lại câu trả lời. Đối tượng của tôi đang được tuần tự hóa objvà đã được xác định. Thêm một XMLSerializerNamespace với một không gian tên trống duy nhất vào bộ sưu tập thực hiện một mẹo nhỏ.

Trong VB như thế này:

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

trong C # như thế này:

//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
Tôi đã thử điều này trong VB, các thuộc tính xsi và xsd đã biến mất nhưng các thuộc tính như xmlns: q12 =, d3p1: type và xmlns: d3p1 xuất hiện.
MiddleKay

16
Tôi đã thử phiên bản C # và nó đã loại bỏ xsi và xsd nhưng thêm tiền tố q1: vào tất cả các tên thẻ XML, điều mà tôi không muốn. Có vẻ như ví dụ C # chưa hoàn thành, tham chiếu đến myXmlTextWriter mà tôi cho rằng cần được khởi tạo theo cách giống như ví dụ VB.
redtetrahedron

1
@redtetrahedron Bạn đã tìm ra cách để loại bỏ những thứ q1tào lao chưa?
nghiền nát

Tham khảo câu trả lời stackoverflow.com/questions/31946240/… , nếu q1 được thêm vào dưới dạng không gian tên trống
aniruddha

20

Nếu bạn muốn loại bỏ phần thừa xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"nhưng vẫn giữ không gian tên của riêng mình xmlns="http://schemas.YourCompany.com/YourSchema/", bạn sử dụng mã tương tự như trên ngoại trừ thay đổi đơn giản này:

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

13

Nếu bạn muốn xóa không gian tên, bạn cũng có thể muốn xóa phiên bản, để tiết kiệm cho việc tìm kiếm, tôi đã thêm chức năng đó nên đoạn mã dưới đây sẽ thực hiện cả hai.

Tôi cũng đã gói nó trong một phương pháp chung vì tôi đang tạo các tệp xml rất lớn, quá lớn để tuần tự hóa trong bộ nhớ vì vậy tôi đã chia nhỏ tệp đầu ra của mình và tuần tự hóa nó thành các "phần" nhỏ hơn:

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

Hãy cẩn thận, StringWritermặc định là Mã hóa UTF-16 có thể dẫn đến các vấn đề về không gian hóa ở hạ lưu. using (var reader = XmlReader.Create(stream)){ reader.Read(); }Điều này ném ra một ngoại lệ vì tuyên bố nói rằng nó là UTF-16 trong khi nội dung thực sự được viết là UTF-8. System.Xml.XmlException: 'There is no Unicode byte order mark. Cannot switch to Unicode.'
Tyler StandishMan

Để giải quyết vấn đề này và vẫn sử dụng XmlReader, bạn có thể sử dụng var streamReader = new StreamReader(stream, System.Text.Encoding.UTF8, true);The true sẽ sử dụng BOM nếu được tìm thấy, nếu không, bạn cung cấp giá trị mặc định.
Tyler StandishMan

9

Tôi đề xuất lớp người trợ giúp này:

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
}

:)


câu trả lời tuyệt vời :) tôi cũng đã thêm dòng dòng này.Position = 0; và trả lại toàn bộ hoạt động vào giải pháp của tôi .. làm việc như mong đợi - tất cả các thẻ giảm tốc đã được gỡ bỏ
ymz

Chỉ riêng việc thêm đối số không gian tên vào lệnh gọi trình tuần tự đã giúp tôi xóa không gian tên mặc định. Viết new XmlSerializerNamespaces(new[] {XmlQualifiedName.Empty})thay vì new XmlSerializerNamespaces(new[] {new XmlQualifiedName("", "")})là một cách có chủ ý rõ ràng hơn để viết mã nó, theo ý kiến ​​của tôi.
Suncat2000

5

Nếu bạn không thể loại bỏ các thuộc tính xmlns bổ sung cho mỗi phần tử, khi tuần tự hóa thành xml từ các lớp được tạo (ví dụ: khi xsd.exe được sử dụng), bạn có một số thứ như sau:

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

sau đó tôi sẽ chia sẻ với bạn những gì phù hợp với tôi (kết hợp giữa các câu trả lời trước đó và những gì tôi tìm thấy ở đây )

đặt rõ ràng tất cả các xmlns khác nhau của bạn như sau:

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

sau đó chuyển nó vào serialize

serializer.Serialize(writer, object, xmlns);

bạn sẽ có ba không gian tên được khai báo trong phần tử gốc và không cần tạo thêm trong các phần tử khác mà sẽ có tiền tố tương ứng

<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();
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.