我可以有空属性和其他属性在相同的标记在XML中创建的XSD c#生成类
本文关键字:属性 XSD 创建 XML 其他 我可以 | 更新日期: 2023-09-27 18:15:52
我有一堆c#类,它们是从XSD自动生成的。然后基于这些c#类生成XML文件。到目前为止还不存在。
问题:
生成的XML文件正在经过验证,并且验证需要为所有带有xsi:nil="true"
的XML标记添加一个额外的属性。基本上标签应该看起来像:<testTag.01 xsi:nil="true" NV="123123" />
,但我不能在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 //}
此代码生成<testTag.01>SomeValue</testTag.01>
或<testTag.01 xsi:nil="true"/>
。
如果取消ELSE的注释,结果将是:<testTag.01>SomeValue</testTag.01>
或<testTag.01 NV="123123" />
。
所以我不知道如何获得验证工具所需的格式。有什么想法吗?
公立小学下面是自动生成的c#类:///[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd","4.0.30319.33440")][System.SerializableAttribute ())[System.Diagnostics.DebuggerStepThroughAttribute ()][System.ComponentModel.DesignerCategoryAttribute("代码"))[System.Xml.Serialization.XmlTypeAttribute AnonymousType = true,名称空间= " http://www.blabla.org ")
公共部分类testTag01 {
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为空。public SomeEnum? Value
,但抛出异常:
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"
和content的元素将违反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");
}
}
}
XML输出如下:
<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>
或
<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>
Prototype fiddle使用这些扩展方法:
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();
}
}
}
正如预期的那样,没有现成的解决方案,所以我即兴发挥了一下,并在后处理逻辑中实现了我的目标。
我正在解析生成的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模式,我的解决方案不需要任何额外的工作。谢谢。