我可以在由XSD C#生成的类创建的XML中的同一标记处具有null属性和其他属性吗?

我有一堆C#类,它们是从XSD自动生成的。 然后我基于那些C#类生成XML文件。 到目前为止还没有任何东西

问题:

生成的XML文件正在进行validation,validation需要使用xsi:nil="true"所有XML标记的额外属性。 基本上标签应该如下所示: ,但我无法在C#中实现。 我的代码是:

  if (myObject.TestTag.HasValue) { t.testTag01 = new testTag01(); t.testTag01.Value = myObject.TestTag.Value; } //else //{ // t.testTag01 = new testTag01(); // t.testTag01.NV = "123123";//Not Recorded //} 

此代码生成SomeValue

如果我取消注释ELSE ,结果将是: SomeValue

所以我不知道如何获得validation工具所需的格式。 有任何想法吗 ?

PS

这是自动生成的C#类:

/// [System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”,“4.0.30319.33440”)] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute(“code”) ] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true,Namespace =“http://www.blabla.org”)]

public partial class testTag01 {

 private string nvField; private SomeEnum valueField; ///  [System.Xml.Serialization.XmlAttributeAttribute()] public string NV { get { return this.nvField; } set { this.nvField = value; } } ///  [System.Xml.Serialization.XmlTextAttribute()] public SomeEnum Value { get { return this.valueField; } set { this.valueField = value; } } } 

我不想改变这一部分,但我知道如果不这样做就不可能。 我也尝试将SomeEnum设置为Nullable。 public SomeEnum? Value public SomeEnum? Value ,但抛出exception:

 Cannot serialize member 'Value' of type System.Nullable`1[]. XmlAttribute/XmlText cannot be used to encode complex types. 

XmlSerializer不直接支持绑定到同时具有xsi:nil="true"元素以及其他属性值; 请参阅Xsi:nil属性绑定支持 :nil属性和其他属性 。

因此,您需要手动发出属性。

如果您希望能够生成一个没有内容和两个属性的元素,一个名为NV而另一个属于xsi:nil="true" ,则可以修改testTag01类以获得NV属性以及合成属性拥有正确的命名空间和名称:

 public class testTag01 { [XmlAttribute] public string NV { get; set; } [XmlAttribute("nil", Namespace = "http://www.w3.org/2001/XMLSchema-instance")] public string Nil { get { return "true"; } set { } } } 

如果你有时想要xsi:nil="true"但是在其他时候希望元素具有与你的SomeEnum相对应的内容,你需要做一些更复杂的事情,因为必须抑制xsi:nil="true"当元素有内容时:

 public class testTag01 { [XmlAttribute] public string NV { get; set; } [XmlAttribute("nil", Namespace = "http://www.w3.org/2001/XMLSchema-instance")] public string Nil { get { return SomeEnum == null ? "true" : null; } set { } } public bool ShouldSerializeNil() { return SomeEnum == null; } [XmlIgnore] public SomeEnum? SomeEnum { get; set; } [XmlText] public string SomeEnumText { get { if (SomeEnum == null) return null; return SomeEnum.Value.ToString(); } set { // See here if one needs to parse XmlEnumAttribute attributes // http://stackoverflow.com/questions/3047125/retrieve-enum-value-based-on-xmlenumattribute-name-value value = value.Trim(); if (string.IsNullOrEmpty(value)) SomeEnum = null; else { try { SomeEnum = (SomeEnum)Enum.Parse(typeof(SomeEnum), value, false); } catch (Exception) { SomeEnum = (SomeEnum)Enum.Parse(typeof(SomeEnum), value, true); } } } } } 

(同时具有xsi:nil="true"和内容的元素将违反XML标准 ;希望您没有。)

然后使用它像:

 public class TestClass { [XmlElement("testTag.01")] public testTag01 TestTag { get; set; } public static void Test() { Test(new TestClass { TestTag = new testTag01 { NV = "123123" } }); Test(new TestClass { TestTag = new testTag01 { NV = "123123", SomeEnum = SomeEnum.SomeValue } }); } private static void Test(TestClass test) { var xml = test.GetXml(); var test2 = xml.LoadFromXML(); Console.WriteLine(test2.GetXml()); Debug.WriteLine(test2.GetXml()); if (test2.TestTag.NV != test.TestTag.NV) { throw new InvalidOperationException("test2.TestTag.NV != test.TestTag.NV"); } } } 

XML输出如下所示:

    

要么

  SomeValue  

使用这些扩展方法的原型小提琴 :

 public static class XmlSerializationHelper { public static T LoadFromXML(this string xmlString, XmlSerializer serializer = null) { T returnValue = default(T); using (StringReader reader = new StringReader(xmlString)) { object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); if (result is T) { returnValue = (T)result; } } return returnValue; } public static string GetXml(this T obj, XmlSerializerNamespaces ns = null, XmlWriterSettings settings = null, XmlSerializer serializer = null) { using (var textWriter = new StringWriter()) { settings = settings ?? new XmlWriterSettings() { Indent = true, IndentChars = " " }; // For cosmetic purposes. using (var xmlWriter = XmlWriter.Create(textWriter, settings)) (serializer ?? new XmlSerializer(typeof(T))).Serialize(xmlWriter, obj, ns); return textWriter.ToString(); } } } 

正如预期的那样,开箱即用的情况没有解决方案,所以我即兴发挥了一点,并在后期处理逻辑中实现了我的目标。

我正在解析生成的XML,如果我正在寻找具有xsi:nil属性但没有NV属性的节点 – 我将使用默认值添加NV属性。 具有NV属性的节点相同,但没有xsi:nil。

这是代码:

  XmlDocument doc = new XmlDocument();// instantiate XmlDocument and load XML from file doc.Load("somepath.xml"); //Get the nodes with NV attribute(using XPath) and add xsi:nill to that nodes XmlNodeList nodes = doc.SelectNodes("//*[@NV]"); foreach (XmlNode node in nodes) { XmlAttribute nilAttr = doc.CreateAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"); nilAttr.Value = "true"; node.Attributes.Append(nilAttr); } //Get the nodes with xsi:nill attribute(using XPath) and add NV with default value to that nodes XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable); nsManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); XmlNodeList nilNodes = doc.SelectNodes("//*[@xsi:nil]", nsManager); foreach (XmlNode node in nilNodes) { XmlAttribute nvAttr = doc.CreateAttribute("NV"); nvAttr.Value = "7701003"; node.Attributes.Append(nvAttr); } doc.Save("somepath.xml"); 

上面的答案是完全有道理的,但由于这些类是自动生成的,我会按照后处理的方式进行,因为如果提供者更改XSD架构,我的解决方案不需要任何额外的工作。 不管怎么说,还是要谢谢你。