在 C# 中使用 xsi:nil="true" 反序列化 XML 元素
Deserialize XML element with xsi:nil="true" in C#
我正在尝试在 C# 中使用 XmlSerializer
反序列化一个 XML 文件。
随后的目的地 class 是使用 xsd 实用程序自动生成的。
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)]
public partial class location
{
private string cityField;
private string countryField;
private string stateField;
private string textField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string city
{
get
{
return this.cityField;
}
set
{
this.cityField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string country
{
get
{
return this.countryField;
}
set
{
this.countryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string state
{
get
{
return this.stateField;
}
set
{
this.stateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Text
{
get
{
return this.textField;
}
set
{
this.textField = value;
}
}
}
在我到达文件的这一部分之前一切正常:
<locations>
<location country="PARAGUAY" city="Ciudad del Este" state="Alto Parana" xsi:nil="true"/>
<location country="BRAZIL" city="Passo Fundo" state="Rio Grande do Sul" xsi:nil="true"/>
</locations>
与stated in the MSDN一样,xsi:nil="true"的元素将被反序列化为空对象,完全失去所有属性。在 C# 中,这转换为空对象。
有没有办法改变这种行为,以便反序列化这三个属性?
提前感谢您的任何建议!
编辑 1:
这是关联的命名空间:
<records xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="structure.xsd">
(location is within here somewhere)
</records>
尝试使用自定义 XmlReader
。当无法更改用于反序列化的 类 时,此方法可能很有用。而且它不需要额外的内存消耗。
public class NilIgnoreReader : XmlTextReader
{
public NilIgnoreReader(string url) : base(url) { }
bool isLocation = false;
public override bool Read()
{
bool read = base.Read();
if (NodeType == XmlNodeType.Element && LocalName == "location")
isLocation = true;
return read;
}
public override string GetAttribute(string localName, string namespaceURI)
{
if (isLocation && localName == "nil" &&
namespaceURI == "http://www.w3.org/2001/XMLSchema-instance")
{
isLocation = false;
return "false";
}
return base.GetAttribute(localName, namespaceURI);
}
}
NilIgnoreReader
return false
for nil
属性从 location
元素绑定到 http://www.w3.org/2001/XMLSchema-instance
命名空间。
用法
var xs = new XmlSerializer(typeof(Records));
Records record;
using (var reader = new NilIgnoreReader("test.xml"))
record = (Records)xs.Deserialize(reader);
它适用于 XML 就像
<?xml version="1.0"?>
<records xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="structure.xsd">
<locations>
<location country="PARAGUAY" city="Ciudad del Este" state="Alto Parana" xsi:nil="true"/>
<location country="BRAZIL" city="Passo Fundo" state="Rio Grande do Sul" xsi:nil="true"/>
</locations>
</records>
和类喜欢
[XmlRoot("records")]
public class Records
{
[XmlArray("locations")]
[XmlArrayItem("location")]
public Location[] Locations { get; set; }
}
public class Location
{
[XmlAttribute("country")]
public string Country { get; set; }
[XmlAttribute("city")]
public string City { get; set; }
[XmlAttribute("state")]
public string State { get; set; }
}
如果您只是想丢弃 xsi:nil
属性,请在包含 class 的 属性 的 [XmlElement]
属性中设置 XmlElementAttribute.IsNullable = false
至 location
。
例如。如果你有
[System.Xml.Serialization.XmlRootAttribute("locations", Namespace = "")]
public class LocationList
{
[XmlElement("location", IsNullable = true)]
public List<location> Locations { get; set; }
}
手动更改为:
[System.Xml.Serialization.XmlRootAttribute("locations", Namespace = "")]
public class LocationList
{
[XmlElement("location", IsNullable = false)]
public List<location> Locations { get; set; }
}
如果你想绑定到xsi:nil
的值同时绑定到其他属性值,除了设置IsNullable = false
,你可以按照 :
中显示的行添加手册 属性
public partial class location
{
bool nil;
[XmlAttribute("nil", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public bool Nil
{
get
{
return nil;
}
set
{
nil = value;
}
}
public bool ShouldSerializeNil() { return nil == true; }
}
示例 fiddle.
您还可以预处理和 post 处理 XML 以重命名 xsi:nil
属性,如 .
中所建议
我正在尝试在 C# 中使用 XmlSerializer
反序列化一个 XML 文件。
随后的目的地 class 是使用 xsd 实用程序自动生成的。
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)]
public partial class location
{
private string cityField;
private string countryField;
private string stateField;
private string textField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string city
{
get
{
return this.cityField;
}
set
{
this.cityField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string country
{
get
{
return this.countryField;
}
set
{
this.countryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string state
{
get
{
return this.stateField;
}
set
{
this.stateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Text
{
get
{
return this.textField;
}
set
{
this.textField = value;
}
}
}
在我到达文件的这一部分之前一切正常:
<locations>
<location country="PARAGUAY" city="Ciudad del Este" state="Alto Parana" xsi:nil="true"/>
<location country="BRAZIL" city="Passo Fundo" state="Rio Grande do Sul" xsi:nil="true"/>
</locations>
与stated in the MSDN一样,xsi:nil="true"的元素将被反序列化为空对象,完全失去所有属性。在 C# 中,这转换为空对象。
有没有办法改变这种行为,以便反序列化这三个属性?
提前感谢您的任何建议!
编辑 1:
这是关联的命名空间:
<records xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="structure.xsd">
(location is within here somewhere)
</records>
尝试使用自定义 XmlReader
。当无法更改用于反序列化的 类 时,此方法可能很有用。而且它不需要额外的内存消耗。
public class NilIgnoreReader : XmlTextReader
{
public NilIgnoreReader(string url) : base(url) { }
bool isLocation = false;
public override bool Read()
{
bool read = base.Read();
if (NodeType == XmlNodeType.Element && LocalName == "location")
isLocation = true;
return read;
}
public override string GetAttribute(string localName, string namespaceURI)
{
if (isLocation && localName == "nil" &&
namespaceURI == "http://www.w3.org/2001/XMLSchema-instance")
{
isLocation = false;
return "false";
}
return base.GetAttribute(localName, namespaceURI);
}
}
NilIgnoreReader
return false
for nil
属性从 location
元素绑定到 http://www.w3.org/2001/XMLSchema-instance
命名空间。
用法
var xs = new XmlSerializer(typeof(Records));
Records record;
using (var reader = new NilIgnoreReader("test.xml"))
record = (Records)xs.Deserialize(reader);
它适用于 XML 就像
<?xml version="1.0"?>
<records xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="structure.xsd">
<locations>
<location country="PARAGUAY" city="Ciudad del Este" state="Alto Parana" xsi:nil="true"/>
<location country="BRAZIL" city="Passo Fundo" state="Rio Grande do Sul" xsi:nil="true"/>
</locations>
</records>
和类喜欢
[XmlRoot("records")]
public class Records
{
[XmlArray("locations")]
[XmlArrayItem("location")]
public Location[] Locations { get; set; }
}
public class Location
{
[XmlAttribute("country")]
public string Country { get; set; }
[XmlAttribute("city")]
public string City { get; set; }
[XmlAttribute("state")]
public string State { get; set; }
}
如果您只是想丢弃 xsi:nil
属性,请在包含 class 的 属性 的 [XmlElement]
属性中设置 XmlElementAttribute.IsNullable = false
至 location
。
例如。如果你有
[System.Xml.Serialization.XmlRootAttribute("locations", Namespace = "")]
public class LocationList
{
[XmlElement("location", IsNullable = true)]
public List<location> Locations { get; set; }
}
手动更改为:
[System.Xml.Serialization.XmlRootAttribute("locations", Namespace = "")]
public class LocationList
{
[XmlElement("location", IsNullable = false)]
public List<location> Locations { get; set; }
}
如果你想绑定到xsi:nil
的值同时绑定到其他属性值,除了设置IsNullable = false
,你可以按照
public partial class location
{
bool nil;
[XmlAttribute("nil", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public bool Nil
{
get
{
return nil;
}
set
{
nil = value;
}
}
public bool ShouldSerializeNil() { return nil == true; }
}
示例 fiddle.
您还可以预处理和 post 处理 XML 以重命名 xsi:nil
属性,如