在 C# Web api 中序列化 xml 时删除命名空间内部节点

Sre*_*mat 2 c# xml xmlserializer

我正在使用 webapi MVC 模板 使用默认的 XmlSerializer 我得到以下输出

OUTPUT:
<ClassName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Child1>String</Child>
<Child2 xsi:nil=true/>
</ClassName> 

DTO class
[XmlRoot("ClassName")]
[DataContract]
public class ClassName
{
        [DataMember]
        [XmlElement("Child1")]
        public string Child1{ get; set; }

        [DataMember]
        [XmlElement("Child2",IsNullable =true)]
        public string Child2{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我设法通过覆盖默认的 xmlformatter 来删除根节点命名空间

//Code to remove root node namespace
  using (XmlWriter xw = XmlWriter.Create(streamWriter, settings))
                    {
                        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                        ns.Add("", "");
                        serializer.Serialize(xw, value, ns);

                }
Run Code Online (Sandbox Code Playgroud)

但是现在根节点中的命名空间被删除,但子节点仍然具有命名空间

Current Output:
<ClassName>
    <Child1>String</Child>
    <Child2 xsi:nil=true p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"/>
</ClassName>
Expected output:
    <ClassName>
        <Child1>String</Child>
        <Child2 />
    </ClassName>
Run Code Online (Sandbox Code Playgroud)

dbc*_*dbc 5

"http://www.w3.org/2001/XMLSchema-instance"需要添加命名空间,因为您已指定XmlElementAttribute.IsNullable = truefor Child2文档中对此进行了解释:

结构的 XML 模式规范允许 XML 文档明确指示元素内容丢失。此类元素包含设置为 true 的属性 xsi:nil。有关详细信息,请参阅万维网联盟 (www.w3.org) 规范“XML 架构第 1 部分:结构”。

如果 IsNullable 属性设置为 true,则为已设置为 null 的类成员生成 xsi:nil 属性。例如,如果将名为 MyStringArray 的字段设置为 null,则 XmlSerializer生成以下 XML 代码。

<MyStringArray xsi:nil = "true" />
Run Code Online (Sandbox Code Playgroud)

如果 IsNullable 属性为 false,则不会为已设置为 null 的类成员生成任何 XML 元素。

其中xsiin"xsi:nil"是命名空间的快捷方式,如Xsi:nil 属性绑定支持http://www.w3.org/2001/XMLSchema-instance中所述。正如 w3c 标准属性(在此处定义)一样,省略名称空间将创建接收系统无法正确理解的非标准 XML。请注意,仅在需要时发出属性和关联的命名空间。XML 输出为xsi:nilXmlSerializernil

new ClassName() { Child1 = null, Child2 = string.Empty }
Run Code Online (Sandbox Code Playgroud)

将不包含属性或命名空间。

顺便说一句,为了消除可能的混淆,在 XML

<Child2 xsi:nil=true p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"/>
Run Code Online (Sandbox Code Playgroud)

只有nil属性位于"http://www.w3.org/2001/XMLSchema-instance"命名空间中,因为只有属性才有p2:前缀。该Child2元素本身位于默认命名空间中,因此命名空间的存在不会改变 XML 的整体含义。事实上,没有理由不在根节点上保留xsi和命名空间。xsd由于它们被命名为命名空间而不是默认命名空间,因此只有具有适当前缀的元素和属性才会属于它们。

话虽这么说,如果出于某种原因您必须使用自定义nil属性来表示空文本值,则需要实现自定义属性来序列化和反序列化它,例如:

    [XmlRoot("ClassName")]
    [DataContract]
    public class ClassName
    {
        [DataMember]
        [XmlElement("Child1")]
        public string Child1 { get; set; }

        [DataMember]
        [XmlIgnore]
        public string Child2 { get; set; }

        [XmlElement("Child2")]
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [IgnoreDataMember]
        public CustomXmlNilTextWrapper Child2Xml { get { return Child2; } set { Child2 = value; } }
    }

    public struct CustomXmlNilTextWrapper
    {
        bool forceNull;
        string value;

        public static implicit operator CustomXmlNilTextWrapper(string value)
        {
            return new CustomXmlNilTextWrapper(value);
        }

        public static implicit operator string(CustomXmlNilTextWrapper wrapper)
        {
            return wrapper.Value;
        }

        public CustomXmlNilTextWrapper(string value)
        {
            this.value = value;
            this.forceNull = value == null;
        }

        [XmlAttribute("nil")]
        public bool ForceNull { get { return forceNull; } set { forceNull = value; } }

        public bool ShouldSerializeForceNull() { return ForceNull == true; }

        [XmlText]
        public string Value { get { return ForceNull ? null : value ?? string.Empty; } set { this.value = value; } }
    }
Run Code Online (Sandbox Code Playgroud)

序列化此类的默认实例将产生如下输出:

<ClassName>
    <Child2 nil="true" />
</ClassName>
Run Code Online (Sandbox Code Playgroud)

这满足了您没有名称空间的要求 - 但我认为这不值得麻烦。

原型小提琴展示了一切是如何工作的。