.NET에서 객체를 직렬화 할 때 모든 xsi 및 xsd 네임 스페이스를 생략 하시겠습니까?


132

코드는 다음과 같습니다.

StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
    XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
    s.Serialize(xmlWriter, objectToSerialize);
}

결과 직렬화 된 문서에는 다음과 같은 네임 스페이스가 포함됩니다.

<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 
    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" 
    xmlns="urn:something">
 ...
</message>

xsi 및 xsd 네임 스페이스를 제거하려면 xmlns =”…”를 얻지 않고 객체를 XML로 직렬화하는 방법 의 답변을 따를 수 있습니다 . .

메시지 태그를 <message>네임 스페이스 속성없이 사용 하고 싶습니다 . 어떻게해야합니까?


2
이것이 XML을 더 좋아 보이게 할 수 있다고 생각하지만 네임 스페이스와 해당 xsd를 제공하는 것이 더 좋습니다.

2
XML을 <message>로만 사용하고 싶습니다 .xmlns : xsi 및 xmlns : xsd 네임 스페이스를 생략하는 것에 대해 이야기하고 있습니다.
NetSide

5
기록 : 일반적으로 이것은 어리석은 실수입니다. 네임 스페이스는 이유가 있으므로 모두 제거하면 문제가 발생합니다. 역 직렬화와 같은 것.
John Saunders

66
때로는 어리석지 않고 실수가 아닙니다. 예를 들어, 문서 조각을 생성하여 나중에 정리해야 할 수도 있습니다. 개인적으로, 나는 비슷하고 매우 큰 문서를 많이 만들어야했습니다. 그들 모두는 나무 안에 깊은 부분이 똑 같았습니다. 그래서 나는 불변 부분을 미리 생성하고 문서를 생성 할 때 바이트 배열로 삽입해야했습니다. 따라서 출력을 더 읽기 쉽고 작게 만들려면 내부 부분에서 일부 네임 스페이스 선언이 생략되어 더 높은 수준으로 존재해야했습니다.
Dmitry Tashkinov

답변:


233
...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);

2
기본 네임 스페이스를 제거하면 의도하지 않은 결과가 발생할 수 있다고 덧붙이고 싶습니다. 예를 들어 XmlInclude 특성을 사용하여 파생 유형을 직렬화하면 네임 스페이스가 원하는지 여부에 관계없이 이러한 각 요소에 추가됩니다. deserialization에 필요
Thomas Levesque

3
또한 질문에 따라 모든 xml 네임 스페이스를 제거하지는 않습니다 . stackoverflow.com/questions/258960 질문에서 언급했듯이 xsi 및 xsd 네임 스페이스 만 제거합니다 . 질문 에도 인용되어 있습니다.
Cheeso

1
또한 내 대답에 언급 된 것처럼 MS에서 지원하지 않습니다. 특히 네임 스페이스 있는 다른 유형과 함께 유형을 사용할 수있는 경우 항상 작동하지는 않습니다 .
fourpastmidnight

@ ThomasLevesque, XmlInclude 속성을 사용하는 동안 기본 네임 스페이스를 제거하는 방법은 무엇입니까?
Jeson Martajaya

4
단축 가능s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Xeevis

27

이것은 두 가지 답변 중 두 번째입니다.

직렬화 중에 문서에서 모든 네임 스페이스를 임의로 제거하려는 경우 고유 한 XmlWriter를 구현하여이를 수행 할 수 있습니다.

가장 쉬운 방법은 XmlTextWriter에서 파생하여 네임 스페이스를 내보내는 StartElement 메서드를 재정의하는 것입니다. StartElement 메서드는 루트를 포함한 모든 요소를 ​​방출 할 때 XmlSerializer에 의해 호출됩니다. 각 요소의 네임 스페이스를 재정의하고 빈 문자열로 바꾸면 출력에서 ​​네임 스페이스를 제거했습니다.

public class NoNamespaceXmlWriter : XmlTextWriter
{
    //Provide as many contructors as you need
    public NoNamespaceXmlWriter(System.IO.TextWriter output)
        : base(output) { Formatting= System.Xml.Formatting.Indented;}

    public override void WriteStartDocument () { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement("", localName, "");
    }
}

이것이 유형이라고 가정하십시오.

// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
    // private fields backing the properties
    private int _Epoch;
    private string _Label;

    // explicitly define a distinct namespace for this element
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    // this property will be implicitly serialized to XML using the
    // member name for the element name, and inheriting the namespace from
    // the type.
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }
}

직렬화 중에 이러한 것을 사용하는 방법은 다음과 같습니다.

        var o2= new MyTypeWithNamespaces { ..intializers.. };
        var builder = new System.Text.StringBuilder();
        using ( XmlWriter writer = new NoNamespaceXmlWriter(new System.IO.StringWriter(builder)))
        {
            s2.Serialize(writer, o2, ns2);
        }            
        Console.WriteLine("{0}",builder.ToString());

XmlTextWriter는 다소 고장났습니다. 참조 doc 에 따르면 쓸 때 다음을 확인하지 않습니다.

  • 속성 및 요소 이름에 유효하지 않은 문자가 있습니다.

  • 지정된 인코딩에 맞지 않는 유니 코드 문자 유니 코드 문자가 지정된 인코딩에 맞지 않으면 XmlTextWriter는 유니 코드 문자를 문자 엔터티로 이스케이프하지 않습니다.

  • 속성이 중복되었습니다.

  • DOCTYPE 공용 식별자 또는 시스템 식별자의 문자

XmlTextWriter에 대한 이러한 문제는 .NET Framework v1.1 이후로 발생했으며 이전 버전과의 호환성을 위해 계속 남아 있습니다. 이러한 문제에 대해 걱정이 없다면 반드시 XmlTextWriter를 사용하십시오. 그러나 대부분의 사람들은 조금 더 신뢰성을 원합니다.

그것을 얻으려면 XmlTextWriter에서 파생하는 대신 직렬화 중에 네임 스페이스를 계속 억제하면서 추상 XmlWriter 및 24 메소드 의 구체적인 구현을 정의하십시오 .

예를 들면 다음과 같습니다.

public class XmlWriterWrapper : XmlWriter
{
    protected XmlWriter writer;

    public XmlWriterWrapper(XmlWriter baseWriter)
    {
        this.Writer = baseWriter;
    }

    public override void Close()
    {
        this.writer.Close();
    }

    protected override void Dispose(bool disposing)
    {
        ((IDisposable) this.writer).Dispose();
    }

    public override void Flush()
    {
        this.writer.Flush();
    }

    public override string LookupPrefix(string ns)
    {
        return this.writer.LookupPrefix(ns);
    }

    public override void WriteBase64(byte[] buffer, int index, int count)
    {
        this.writer.WriteBase64(buffer, index, count);
    }

    public override void WriteCData(string text)
    {
        this.writer.WriteCData(text);
    }

    public override void WriteCharEntity(char ch)
    {
        this.writer.WriteCharEntity(ch);
    }

    public override void WriteChars(char[] buffer, int index, int count)
    {
        this.writer.WriteChars(buffer, index, count);
    }

    public override void WriteComment(string text)
    {
        this.writer.WriteComment(text);
    }

    public override void WriteDocType(string name, string pubid, string sysid, string subset)
    {
        this.writer.WriteDocType(name, pubid, sysid, subset);
    }

    public override void WriteEndAttribute()
    {
        this.writer.WriteEndAttribute();
    }

    public override void WriteEndDocument()
    {
        this.writer.WriteEndDocument();
    }

    public override void WriteEndElement()
    {
        this.writer.WriteEndElement();
    }

    public override void WriteEntityRef(string name)
    {
        this.writer.WriteEntityRef(name);
    }

    public override void WriteFullEndElement()
    {
        this.writer.WriteFullEndElement();
    }

    public override void WriteProcessingInstruction(string name, string text)
    {
        this.writer.WriteProcessingInstruction(name, text);
    }

    public override void WriteRaw(string data)
    {
        this.writer.WriteRaw(data);
    }

    public override void WriteRaw(char[] buffer, int index, int count)
    {
        this.writer.WriteRaw(buffer, index, count);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        this.writer.WriteStartAttribute(prefix, localName, ns);
    }

    public override void WriteStartDocument()
    {
        this.writer.WriteStartDocument();
    }

    public override void WriteStartDocument(bool standalone)
    {
        this.writer.WriteStartDocument(standalone);
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        this.writer.WriteStartElement(prefix, localName, ns);
    }

    public override void WriteString(string text)
    {
        this.writer.WriteString(text);
    }

    public override void WriteSurrogateCharEntity(char lowChar, char highChar)
    {
        this.writer.WriteSurrogateCharEntity(lowChar, highChar);
    }

    public override void WriteValue(bool value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(DateTime value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(decimal value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(double value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(int value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(long value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(object value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(float value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(string value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteWhitespace(string ws)
    {
        this.writer.WriteWhitespace(ws);
    }


    public override XmlWriterSettings Settings
    {
        get
        {
            return this.writer.Settings;
        }
    }

    protected XmlWriter Writer
    {
        get
        {
            return this.writer;
        }
        set
        {
            this.writer = value;
        }
    }

    public override System.Xml.WriteState WriteState
    {
        get
        {
            return this.writer.WriteState;
        }
    }

    public override string XmlLang
    {
        get
        {
            return this.writer.XmlLang;
        }
    }

    public override System.Xml.XmlSpace XmlSpace
    {
        get
        {
            return this.writer.XmlSpace;
        }
    }        
}

그런 다음 이전과 같이 StartElement 메소드를 대체하는 파생 클래스를 제공하십시오.

public class NamespaceSupressingXmlWriter : XmlWriterWrapper
{
    //Provide as many contructors as you need
    public NamespaceSupressingXmlWriter(System.IO.TextWriter output)
        : base(XmlWriter.Create(output)) { }

    public NamespaceSupressingXmlWriter(XmlWriter output)
        : base(XmlWriter.Create(output)) { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement("", localName, "");
    }
}

그런 다음이 작가를 다음과 같이 사용하십시오.

        var o2= new MyTypeWithNamespaces { ..intializers.. };
        var builder = new System.Text.StringBuilder();
        var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
        using ( XmlWriter innerWriter = XmlWriter.Create(builder, settings))
            using ( XmlWriter writer = new NamespaceSupressingXmlWriter(innerWriter))
            {
                s2.Serialize(writer, o2, ns2);
            }            
        Console.WriteLine("{0}",builder.ToString());

Oleg Tkachenko 에게 이것에 대한 신용 .


3
LookupPrefix(string ns)모든 스키마 선언을 제거하려면 항상 빈 문자열을 반환 하도록 재정의해야한다는 것을 알았습니다 .
케빈 브록

이것은 기술적으로 질문에 대답하지 않습니다. XmlWriter가 아닌 XmlTextWriter를 사용하고 있습니다. XmlWriter를 사용할 수 있기 때문에 XmlWriterSettings에 대해 XmlWriter를 사용하고 싶습니다.
Abacus

@Abacus 코드를 읽었습니까? 그것은 사용 XmlWriter 하고 XmlWriterSettings .
Cheeso

내 나쁜, 나는 그것을 그리워해야합니다.
Abacus

훌륭한 답변, @KevinBrock에서 추가 된 메소드 외에도 코드에서 모든 코드를 제거하기 전에 <!-language : lang-cs-> WriteStartAttribute (string prefix, string localName, string ns)를 오버로드해야했습니다. 네임 스페이스. 또한 네임 스페이스 접두사가 b2p1에서 p2로 변경되어 접두사를 사용하는 다른 방법을 확인하게되었습니다.
Mabdullah

15

Microsoft의 설명서와 여러 가지 솔루션을 온라인에서 읽은 후이 문제에 대한 해결책을 찾았습니다. 를 통해 내장 XmlSerializer및 사용자 정의 XML 직렬화와 함께 작동합니다 IXmlSerialiazble.

다시 말해, 지금 MyTypeWithNamespaces까지이 질문에 대한 답변에 사용 된 것과 동일한 XML 샘플을 사용하겠습니다.

[XmlRoot("MyTypeWithNamespaces", Namespace="urn:Abracadabra", IsNullable=false)]
public class MyTypeWithNamespaces
{
    // As noted below, per Microsoft's documentation, if the class exposes a public
    // member of type XmlSerializerNamespaces decorated with the 
    // XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
    // namespaces during serialization.
    public MyTypeWithNamespaces( )
    {
        this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
            // Don't do this!! Microsoft's documentation explicitly says it's not supported.
            // It doesn't throw any exceptions, but in my testing, it didn't always work.

            // new XmlQualifiedName(string.Empty, string.Empty),  // And don't do this:
            // new XmlQualifiedName("", "")

            // DO THIS:
            new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
            // Add any other namespaces, with prefixes, here.
        });
    }

    // If you have other constructors, make sure to call the default constructor.
    public MyTypeWithNamespaces(string label, int epoch) : this( )
    {
        this._label = label;
        this._epoch = epoch;
    }

    // An element with a declared namespace different than the namespace
    // of the enclosing type.
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        get { return this._label; }
        set { this._label = value; }
    }
    private string _label;

    // An element whose tag will be the same name as the property name.
    // Also, this element will inherit the namespace of the enclosing type.
    public int Epoch
    {
        get { return this._epoch; }
        set { this._epoch = value; }
    }
    private int _epoch;

    // Per Microsoft's documentation, you can add some public member that
    // returns a XmlSerializerNamespaces object. They use a public field,
    // but that's sloppy. So I'll use a private backed-field with a public
    // getter property. Also, per the documentation, for this to work with
    // the XmlSerializer, decorate it with the XmlNamespaceDeclarations
    // attribute.
    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces
    {
        get { return this._namespaces; }
    }
    private XmlSerializerNamespaces _namespaces;
}

이것이이 수업의 전부입니다. 이제 일부는XmlSerializerNamespaces 는 자신의 클래스 내에 객체 . 그러나 당신이 볼 수 있듯이, 나는 기본 생성자에 깔끔하게 자리 잡고 네임 스페이스를 반환하는 공용 속성을 노출했습니다.

이제 클래스를 직렬화 할 때 다음 코드를 사용합니다.

MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);

/******
   OK, I just figured I could do this to make the code shorter, so I commented out the
   below and replaced it with what follows:

// You have to use this constructor in order for the root element to have the right namespaces.
// If you need to do custom serialization of inner objects, you can use a shortened constructor.
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces), new XmlAttributeOverrides(),
    new Type[]{}, new XmlRootAttribute("MyTypeWithNamespaces"), "urn:Abracadabra");

******/
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
    new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });

// I'll use a MemoryStream as my backing store.
MemoryStream ms = new MemoryStream();

// This is extra! If you want to change the settings for the XmlSerializer, you have to create
// a separate XmlWriterSettings object and use the XmlTextWriter.Create(...) factory method.
// So, in this case, I want to omit the XML declaration.
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8; // This is probably the default
// You could use the XmlWriterSetting to set indenting and new line options, but the
// XmlTextWriter class has a much easier method to accomplish that.

// The factory method returns a XmlWriter, not a XmlTextWriter, so cast it.
XmlTextWriter xtw = (XmlTextWriter)XmlTextWriter.Create(ms, xws);
// Then we can set our indenting options (this is, of course, optional).
xtw.Formatting = Formatting.Indented;

// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);

이 작업을 완료하면 다음과 같은 결과가 나타납니다.

<MyTypeWithNamespaces>
    <Label xmlns="urn:Whoohoo">myLabel</Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

웹 서비스 호출을 위해 XML로 직렬화되는 클래스가 심층적 인 최근 프로젝트 에서이 방법을 성공적으로 사용했습니다. Microsoft의 문서는 XmlSerializerNamespaces일단 공개적으로 접근 가능한 회원을 만든 후에 는 어떻게해야하는지에 대해 명확하지 않으며 , 많은 사람들이 쓸모 없다고 생각합니다. 그러나 설명서를 따라 위에서 설명한 방식으로 사용하면 XmlSerializer가 지원되지 않는 동작이나 "자신의 롤링"직렬화를 구현하지 않고 클래스에 대해 XML을 생성하는 방법을 사용자 정의 할 수 있습니다.IXmlSerializable .

이 답변이에 의해 생성 된 표준 xsixsd네임 스페이스를 제거하는 방법을 한 번에 쉬게되기를 바랍니다 XmlSerializer.

업데이트 : 모든 네임 스페이스를 제거하는 것에 대한 OP의 질문에 대답하고 싶습니다. 위의 코드는이 작업을 수행합니다. 방법을 보여 드리겠습니다. 위의 예에서 사용중인 네임 스페이스가 두 개이므로 모든 네임 스페이스를 제거 할 수 없습니다. XML 문서 어딘가에와 같은 것이 필요합니다 xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. 예제에서 클래스가 큰 문서의 일부인 경우, 어딘가 네임 스페이스 위 중의 하나 (또는 둘 다)에 대해 선언해야 Abracadbra하고 Whoohoo. 그렇지 않은 경우 네임 스페이스 중 하나 또는 둘 다에있는 요소를 일종의 접두어로 장식해야합니다 (두 개의 기본 네임 스페이스를 가질 수 없습니까?). 따라서이 예에서는 기본 Abracadabra네임 스페이스입니다. MyTypeWithNamespaces클래스 내 에서 네임 스페이스의 네임 스페이스 접두사를 다음 Whoohoo과 같이 추가 할 수 있습니다 .

public MyTypeWithNamespaces
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra"), // Default Namespace
        new XmlQualifiedName("w", "urn:Whoohoo")
    });
}

이제 클래스 정의에서 <Label/>요소가 namespace에 있음을 나타내 "urn:Whoohoo"므로 더 이상 아무것도 할 필요가 없습니다. 위의 직렬화 코드를 변경하지 않고 클래스를 직렬화하면 다음과 같이 출력됩니다.

<MyTypeWithNamespaces xmlns:w="urn:Whoohoo">
    <w:Label>myLabel</w:Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

<Label>문서의 나머지 부분과 다른 네임 스페이스에 있기 때문에 네임 스페이스를 사용하여 "장식"해야합니다. 아무 여전히 있다는 것을 공지 사항 xsixsd네임 스페이스.


"Microsoft의 문서에 따르면 지원되지 않습니다." 어디서 공유 할까?
Dave Van den Eynde

데이브, 당신이 비슷한 질문 XmlSerializer에 대한 답변에 게시 한대로 불필요한 xsi 및 xsd 네임 스페이스를 제거 하면 링크는 다음과 같습니다. XmlSerializerNamespaces Class .
fourpastmidnight

1
여전히 네임 스페이스를 Serialize 메서드에 전달하고 있습니다. 공개 회원을 제공한다는 아이디어는 그렇게하지 않아도된다는 생각이었습니다. Serialize 메서드에 전달하지 않으면 작동하지 않습니다. 불행히도, 나는 그 메소드 호출에 액세스 할 수 없습니다. 사용할 XmlSerializer 인스턴스 만 설정할 수 있습니다.
분쇄

실제로 그것이 xsi 및 xsd 네임 스페이스를 강제로 내 출력으로 강제 XmlWriter하는 것이 포함되어 있음을 알았습니다 XmlMediaTypeFormatter. 이것은 WebApi의 default를 사용하는 사람들에게만 영향을줍니다 XmlMediaTypeFormatter. 소스 코드를 복사하고 네임 스페이스 속성을 Serialize 메서드에 전달 XmlWriter하여 두 가지 기본값을 자동으로 추가 하지 못하도록 수정했습니다 . 이 답변
crush

@crush, 당신과 관련된 대답은 오해의 소지가 있지만 잘못된 주장은 아닙니다. 내 대답의 첫 번째 코드 스 니펫을 보면으로 XmlSerializerNamespaces장식 된 형식의 공개 멤버를 노출 할 때 XmlSerializer의 작동 방식을 명시 적으로 설명하는 주석이 표시 XmlNamespacesDeclarationAttribute됩니다. 이것은 MSDN 에서 직접 가져온 것으로 기본적으로 제공되는 기본 네임 스페이스 대신 선언 된 네임 스페이스를 사용합니다 XmlSerializer.
fourpastmidnight

6

이것은 질문에 대한 두 가지 대답 중 첫 번째입니다.

네임 스페이스를 세밀하게 제어하려는 경우 (예 : 네임 스페이스 중 일부는 생략하고 다른 네임 스페이스는 생략하려는 경우) 또는 한 네임 스페이스를 다른 네임 스페이스로 바꾸려는 경우 XmlAttributeOverrides를 사용하여이 작업을 수행 할 수 있습니다. .

이 유형 정의가 있다고 가정하십시오.

// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
    // private fields backing the properties
    private int _Epoch;
    private string _Label;

    // explicitly define a distinct namespace for this element
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    // this property will be implicitly serialized to XML using the
    // member name for the element name, and inheriting the namespace from
    // the type.
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }
}

그리고이 직렬화 의사 코드 :

        var o2= new MyTypeWithNamespaces() { ..initializers...};
        ns.Add( "", "urn:Abracadabra" );
        XmlSerializer s2 = new XmlSerializer(typeof(MyTypeWithNamespaces));
        s2.Serialize(System.Console.Out, o2, ns);

이 XML과 같은 것을 얻을 수 있습니다 :

<MyTypeWithNamespaces xmlns="urn:Abracadabra">
  <Label xmlns="urn:Whoohoo">Cimsswybclaeqjh</Label>
  <Epoch>97</Epoch>
</MyTypeWithNamespaces>

루트 요소에는 기본 네임 스페이스가 있고 "Label"요소에는 고유 한 네임 스페이스가 있습니다. 이러한 네임 스페이스는 위의 코드에서 형식을 장식하는 특성에 의해 결정되었습니다.

.NET의 Xml 직렬화 프레임 워크에는 실제 코드를 장식하는 속성 을 명시 적으로 재정 의 할 수있는 기능이 포함되어 있습니다. XmlAttributesOverrides 클래스 및 친구들과 함께이 작업을 수행합니다. 동일한 유형을 가지고 다음과 같이 직렬화한다고 가정하십시오.

        // instantiate the container for all attribute overrides
        XmlAttributeOverrides xOver = new XmlAttributeOverrides();

        // define a set of XML attributes to apply to the root element
        XmlAttributes xAttrs1 = new XmlAttributes();

        // define an XmlRoot element (as if [XmlRoot] had decorated the type)
        // The namespace in the attribute override is the empty string. 
        XmlRootAttribute xRoot = new XmlRootAttribute() { Namespace = ""};

        // add that XmlRoot element to the container of attributes
        xAttrs1.XmlRoot= xRoot;

        // add that bunch of attributes to the container holding all overrides
        xOver.Add(typeof(MyTypeWithNamespaces), xAttrs1);

        // create another set of XML Attributes
        XmlAttributes xAttrs2 = new XmlAttributes();

        // define an XmlElement attribute, for a type of "String", with no namespace
        var xElt = new XmlElementAttribute(typeof(String)) { Namespace = ""};

        // add that XmlElement attribute to the 2nd bunch of attributes
        xAttrs2.XmlElements.Add(xElt);

        // add that bunch of attributes to the container for the type, and
        // specifically apply that bunch to the "Label" property on the type.
        xOver.Add(typeof(MyTypeWithNamespaces), "Label", xAttrs2);

        // instantiate a serializer with the overrides 
        XmlSerializer s3 = new XmlSerializer(typeof(MyTypeWithNamespaces), xOver);

        // serialize
        s3.Serialize(System.Console.Out, o2, ns2);

결과는 다음과 같습니다.

<MyTypeWithNamespaces>
  <Label>Cimsswybclaeqjh</Label>
  <Epoch>97</Epoch>
</MyTypeWithNamespaces>

네임 스페이스를 제거했습니다.

논리적 질문은 직렬화 중에 명시 적 재정의를 거치지 않고 임의의 유형에서 모든 네임 스페이스를 제거 할 수 있습니까? 대답은 '예'이며 어떻게해야합니까?


6
XmlSerializer sr = new XmlSerializer(objectToSerialize.GetType());
TextWriter xmlWriter = new StreamWriter(filename);
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
sr.Serialize(xmlWriter, objectToSerialize, namespaces);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.