作者:儒雅的aaaaaaaaaaa | 来源:互联网 | 2023-09-23 13:46
IhaveasetofXMLschemafilesprovidedtome.IcannotchangedtheXMLasthesewillbeupdatedo
I have a set of XML schema files provided to me. I cannot changed the XML as these will be updated on occasion. I am using xsd.exe to convert the schema files to generated c# code. I cannot use any third party tools. Part of one of the XML schema files appears as such:
我有一组XML模式文件提供给我。我无法更改XML,因为这些有时会更新。我正在使用xsd.exe将架构文件转换为生成的c#代码。我不能使用任何第三方工具。其中一个XML模式文件的一部分显示如下:
When converted to c#, I get a result such as this:
当转换为c#时,我得到如下结果:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://abcxyz.com")]
public partial class LocationType
{
private object[] itemsField;
private ItemsChoiceType[] itemsElementNameField;
///
[System.Xml.Serialization.XmlElementAttribute("Address", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("City", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("LocNum", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("Longitude", typeof(decimal), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("State", typeof(LocationTypeState), Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public object[] Items
{
get { return this.itemsField; }
set { this.itemsField = value; }
}
///
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType[] ItemsElementName
{
get { return this.itemsElementNameField; }
set { this.itemsElementNameField = value; }
}
}
Since these all get generated to partial classes, I am free to add additional code. I need to be able to read/set the individual properties, such as Name, Address, City, etc.
由于这些都生成了部分类,我可以自由添加其他代码。我需要能够读取/设置各个属性,例如姓名,地址,城市等。
I need to be able to serialize these objects to match the schema.
我需要能够序列化这些对象以匹配架构。
Is there a way in c# to create a public property that will read or set the value in the Items array at the proper sequence, etc.? ie:
在c#中有没有办法创建一个公共属性,以适当的顺序读取或设置Items数组中的值,等等?即:
public partial class LocationType
{
public string Address
{
get
{
// code here to return the correct Items[] element
}
set
{
// code here to set the correct Items[] element
}
}
}
2 个解决方案
4
What that schema says is that if some outer type contains an element of type LocationType
, one would expect to find inside either
该模式所说的是,如果某个外部类型包含一个类型为LocationType的元素,那么人们可能希望在其中找到
1) A sub-element
, OR
1)子元素
,OR
2) These sub-elements in sequence:
,
,
and
.
2)这些子元素依次为:
,
,
和
。
Thus the data here is polymorphic, even though it isn't being explicitly modeled as such in the c# classes generated by xsd.exe. This sort of makes sense -- a location might be specified explicitly, or indirectly as a look-up in a table.
因此,这里的数据是多态的,即使它没有在xsd.exe生成的c#类中明确建模。这种情况很有意义 - 可以明确指定位置,也可以间接指定为表中的查找。
When deserializing a polymorphic sequence like this, XmlSerializer
puts each element it finds in the array field corresponding to the elements in the sequence, in this case the array Items
. In addition, there should be another corresponding array field identified by the XmlChoiceIdentifierAttribute
attribute, in this case ItemsElementName
. The entries in this array must needs be in 1-1 correspondence with the Items
array. It records the name of the element that was deserialized in each index of the Items
array, by way of the ItemsChoiceType
enumeration, whose enum names must match the names in the XmlElementAttribute
attributes decorating the Items
array. This allows the specific choice of polymorphic data to be known.
当像这样反序列化多态序列时,XmlSerializer将它找到的每个元素放在对应于序列中元素的数组字段中,在本例中是数组Items。此外,应该有另一个由XmlChoiceIdentifierAttribute属性标识的相应数组字段,在本例中为ItemsElementName。此数组中的条目必须与Items数组1-1对应。它通过ItemsChoiceType枚举记录Items数组的每个索引中反序列化的元素的名称,其枚举名称必须与装饰Items数组的XmlElementAttribute属性中的名称匹配。这允许已知多态数据的特定选择。
Thus, to round out the implementation of your LocationType
class, you will need to determine whether a given LocationType
is direct or indirect; fetch various properties out; and for each type (direct or indirect), set all required data.
因此,为了完善LocationType类的实现,您需要确定给定的LocationType是直接还是间接;获取各种属性;对于每种类型(直接或间接),设置所有必需的数据。
Here is a prototype of that. (You didn't include the definition for LocationTypeState
in your question, so I'm just treating it as a string):
这是原型。 (你没有在你的问题中包含LocationTypeState的定义,所以我只是将它视为一个字符串):
public partial class LocationType
{
public LocationType() { }
public LocationType(string locNum)
{
SetIndirectLocation(locNum);
}
public LocationType(string name, string address, string city, string state)
{
SetDirectLocation(name, address, city, state);
}
public bool IsIndirectLocation
{
get
{
return Array.IndexOf(ItemsElementName, ItemsChoiceType.LocNum) >= 0;
}
}
public string Address { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.Address); } }
public string LocNum { get { return (string)XmlPolymorphicArrayHelper.GetItem(Items, ItemsElementName, ItemsChoiceType.LocNum); } }
// Other properties as desired.
public void SetIndirectLocation(string locNum)
{
if (string.IsNullOrEmpty(locNum))
throw new ArgumentException();
object[] newItems = new object[] { locNum };
ItemsChoiceType [] newItemsElementName = new ItemsChoiceType [] { ItemsChoiceType.LocNum };
this.Items = newItems;
this.ItemsElementName = newItemsElementName;
}
public void SetDirectLocation(string name, string address, string city, string state)
{
// In the schema, "City" is mandatory, others are optional.
if (string.IsNullOrEmpty(city))
throw new ArgumentException();
List newItems = new List();
List newItemsElementName = new List();
if (name != null)
{
newItems.Add(name);
newItemsElementName.Add(ItemsChoiceType.Name);
}
if (address != null)
{
newItems.Add(address);
newItemsElementName.Add(ItemsChoiceType.Address);
}
newItems.Add(city);
newItemsElementName.Add(ItemsChoiceType.City);
if (state != null)
{
newItems.Add(state);
newItemsElementName.Add(ItemsChoiceType.State);
}
this.Items = newItems.ToArray();
this.ItemsElementName = newItemsElementName.ToArray();
}
}
public static class XmlPolymorphicArrayHelper
{
public static TResult GetItem(TResult[] items, TIDentifier[] itemIdentifiers, TIDentifier itemIdentifier)
{
if (itemIdentifiers == null)
{
Debug.Assert(items == null);
return default(TResult);
}
Debug.Assert(items.Length == itemIdentifiers.Length);
var i = Array.IndexOf(itemIdentifiers, itemIdentifier);
if (i <0)
return default(TResult);
return items[i];
}
}