我有一堆C#类,它们是从XSD自动生成的.然后我基于那些C#类生成XML文件.到目前为止还没有任何东西
问题:
生成的XML文件正在通过验证,验证需要一个额外的属性到所有XML标签xsi:nil="true".基本上标签看起来应该像: <testTag.01 xsi:nil="true" NV="123123" />但我无法在C#中实现.我的代码是:
Run Code Online (Sandbox Code Playgroud)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 //}
此代码生成<testTag.01>SomeValue</testTag.01>或<testTag.01 xsi:nil="true"/>.
如果我取消注释ELSE,结果将是:<testTag.01>SomeValue</testTag.01>或<testTag.01 NV="123123" />.
所以我不知道如何获得验证工具所需的格式.有任何想法吗 ?
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 {
Run Code Online (Sandbox Code Playgroud)private string nvField; private SomeEnum valueField; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string NV { get { return this.nvField; } set { this.nvField = value; } } /// <remarks/> [System.Xml.Serialization.XmlTextAttribute()] public SomeEnum Value { get { return this.valueField; } set { this.valueField = value; } } }
我不想改变那一部分,但我知道如果不这样做就不可能.我也尝试将SomeEnum设置为Nullable.public SomeEnum? Value,但是抛出异常:
Cannot serialize member 'Value' of type System.Nullable`1[]. XmlAttribute/XmlText cannot be used to encode complex types.
Run Code Online (Sandbox Code Playgroud)
XmlSerializer不直接支持绑定到同时具有xsi:nil="true"其他属性值的元素;请参阅Xsi:nil 属性绑定支持:nil 属性和其他属性。
因此,您需要手动发出该属性。
如果您希望能够生成一个没有内容和两个属性的元素,一个属性为 name 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 { } }
}
Run Code Online (Sandbox Code Playgroud)
如果您有时想要拥有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);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(同时具有 和 内容的元素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<TestClass>();
Console.WriteLine(test2.GetXml());
Debug.WriteLine(test2.GetXml());
if (test2.TestTag.NV != test.TestTag.NV)
{
throw new InvalidOperationException("test2.TestTag.NV != test.TestTag.NV");
}
}
}
Run Code Online (Sandbox Code Playgroud)
XML 输出如下所示:
Run Code Online (Sandbox Code Playgroud)<TestClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <testTag.01 NV="123123" xsi:nil="true" /> </TestClass>
或者
Run Code Online (Sandbox Code Playgroud)<TestClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <testTag.01 NV="123123">SomeValue</testTag.01> </TestClass>
使用这些扩展方法的原型小提琴:
public static class XmlSerializationHelper
{
public static T LoadFromXML<T>(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<T>(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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1230 次 |
| 最近记录: |