删除命名空间内部节点,同时在c#web api中获取serml xml

时间:2016-02-29 10:19:10

标签: 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; }
}

我设法通过覆盖默认的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);

                }

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

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>

1 个答案:

答案 0 :(得分:4)

要添加名称空间"http://www.w3.org/2001/XMLSchema-instance" ,因为您已为Child2指定了XmlElementAttribute.IsNullable = true。这在documentation

中有解释
  

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

     

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

<MyStringArray xsi:nil = "true" />
     

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

xsi中的"xsi:nil"http://www.w3.org/2001/XMLSchema-instanceXsi:nil Attribute Binding Support中解释的命名空间xsi:nil的快捷方式。由于XmlSerializer是w3c标准属性(已定义here),因此省略命名空间会创建接收系统无法正确理解的非标准XML。请注意,nil仅在需要时才会发出new ClassName() { Child1 = null, Child2 = string.Empty } 属性和关联的命名空间。

的XML输出
<Child2 xsi:nil=true p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"/>

不包含属性或命名空间。

顺便提一下,要在XML中清除可能的混淆

nil

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

话虽如此,如果由于某种原因你必须使用自定义 [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; } } } 属性来表示空文本值,你需要实现一个自定义属性来序列化和反序列化它,例如:

<ClassName>
    <Child2 nil="true" />
</ClassName>

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

<Page x:Class="HHT.Table"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:local="clr-namespace:HHT"
  mc:Ignorable="d"
  Title="Table" Height="520" Width="985">

  <Grid Margin="0,0,-505,-120" HorizontalAlignment="Left" Width="805" Height="420" VerticalAlignment="Top">
    <Grid.ColumnDefinitions>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <DataGrid x:Name="dataGrid" SelectionChanged="dataGrid_SelectionChanged" Margin="0,0,70,30" HorizontalAlignment="Right" Width="725">
      <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding XPath=@ID}"></DataGridTextColumn>
        <DataGridTextColumn Header="Last Name"></DataGridTextColumn>
        <DataGridTextColumn Header="First Name"></DataGridTextColumn>
        <DataGridTextColumn Header="Birthday"></DataGridTextColumn>
        <DataGridTextColumn Header="Phone Number">    </DataGridTextColumn>
      </DataGrid.Columns>
    </DataGrid>

  </Grid>
</Page>

这符合你没有命名空间的要求 - 但在我看来这不值得。

原型fiddle展示了一切如何运作。