xmlns =“…”없이 객체를 XML로 직렬화하는 방법은 무엇입니까?


109

XML 네임 스페이스가 자동으로 직렬화되지 않고 .NET에서 개체를 직렬화하는 방법이 있습니까? 기본적으로 .NET은 XSI 및 XSD 네임 스페이스가 포함되어야한다고 생각하는 것 같습니다.

답변:


142

아 ... 신경 쓰지 마. 항상 질문이 제기 된 후 검색이 답을 얻습니다. 직렬화되는 내 개체는obj 는 이미 정의되어 있습니다. 하나의 빈 네임 스페이스가있는 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 : 접두사를 추가했습니다. VB 예제와 동일한 방식으로 초기화해야한다고 가정하는 myXmlTextWriter를 참조하는 C # 예제가 불완전한 것 같습니다.
redtetrahedron

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.'
Tyler StandishMan

이 문제를 해결하고 계속 사용 XmlReader하려면 var streamReader = new StreamReader(stream, System.Text.Encoding.UTF8, true);The true는 BOM이 있으면 BOM을 사용하고 그렇지 않으면 사용자가 제공하는 기본값을 사용할 수 있습니다.
Tyler 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

serializer 호출에 namespaces 인수를 추가하는 것만으로도 기본 네임 스페이스를 제거 할 수있었습니다. 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);

루트 요소에 세 개의 네임 스페이스가 선언되고 그에 따라 접두사가 붙는 다른 요소에서 더 이상 생성 할 필요가 없습니다.

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