以编程方式控制 xml 元素的顺序
Posted
技术标签:
【中文标题】以编程方式控制 xml 元素的顺序【英文标题】:Programmatically controlling the order of xml elements 【发布时间】:2011-10-09 06:01:06 【问题描述】:我在我的 .Net 应用程序中使用第三方网络服务 [WS]。 我的应用程序正在使用从这个 WS 的 wsdl 生成的实体类。 我从 db 中获取数据,将其填充到实体对象中,然后使用 XmlSerializer 类从中生成一个 xml。
WS 的其中一种方法需要此 xml 字符串作为输入。并且 xml 应该具有与 WS 预期的顺序相同的元素。但是发生的事情是一些元素在我的应用程序中颠倒了,并且所以 WS 在序列化上抛出了一个最里面的异常:。 _innerException “不一致的顺序:如果用于类的成员之一,所有类粒子成员都需要'Order'属性,请使用类成员的XmlElement,XmlAnyElement或XmlArray自定义属性显式设置'Order''仪器'。" System.Exception System.InvalidOperationException
XmlSerializer serializer = new XmlSerializer(typeof(totemmessage));
所以,我的问题是,在将这些 xml 元素发送到 WS 之前,如何以编程方式控制这些 xml 元素在我的应用程序中的顺序?注意:我不想为此目的使用 xslt。
感谢阅读。
这是我的实体类:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="totem-message")]
[System.Xml.Serialization.XmlRootAttribute("totem", Namespace="", IsNullable=false)]
public partial class totemmessage
private object itemField;
private ItemChoiceType1 itemElementNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("error", typeof(errorinfo))]
[System.Xml.Serialization.XmlElementAttribute("parseReport", typeof(parseReportinfo))]
[System.Xml.Serialization.XmlElementAttribute("results", typeof(templateinfo))]
[System.Xml.Serialization.XmlElementAttribute("subareas", typeof(subareasinfo))]
[System.Xml.Serialization.XmlElementAttribute("template", typeof(templateinfo))]
[System.Xml.Serialization.XmlElementAttribute("upload", typeof(templateinfo))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
[System.Xml.Serialization.XmlElement(Order = 0)]
public object Item
get
return this.itemField;
set
this.itemField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 1)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemChoiceType1 ItemElementName
get
return this.itemElementNameField;
set
this.itemElementNameField = value;
[System.Xml.Serialization.XmlIncludeAttribute(typeof(energyInstrument))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public abstract partial class abstractEnergyInstrument
private energyContractTime periodField;
private bool periodFieldSpecified;
private System.DateTime startDateField;
private bool startDateFieldSpecified;
private System.DateTime endDateField;
private bool endDateFieldSpecified;
private System.DateTime expiryDateField;
private bool expiryDateFieldSpecified;
private energyInstrumentClassifier typeField;
private bool typeFieldSpecified;
private string strikeField;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 0)]
public energyContractTime period
get
return this.periodField;
set
this.periodField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 1)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool periodSpecified
get
return this.periodFieldSpecified;
set
this.periodFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="date", Order =2)]
public System.DateTime startDate
get
return this.startDateField;
set
this.startDateField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 3)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool startDateSpecified
get
return this.startDateFieldSpecified;
set
this.startDateFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="date", Order =4)]
public System.DateTime endDate
get
return this.endDateField;
set
this.endDateField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 5)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool endDateSpecified
get
return this.endDateFieldSpecified;
set
this.endDateFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="date", Order =6)]
public System.DateTime expiryDate
get
return this.expiryDateField;
set
this.expiryDateField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 7)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool expiryDateSpecified
get
return this.expiryDateFieldSpecified;
set
this.expiryDateFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 8)]
public energyInstrumentClassifier type
get
return this.typeField;
set
this.typeField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 9)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool typeSpecified
get
return this.typeFieldSpecified;
set
this.typeFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 10)]
public string strike
get
return this.strikeField;
set
this.strikeField = value;
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlRootAttribute("instrument", Namespace="", IsNullable=false)]
public partial class energyInstrument : abstractEnergyInstrument
private decimal priceField;
private bool priceFieldSpecified;
private decimal forwardField;
private bool forwardFieldSpecified;
private decimal volField;
private bool volFieldSpecified;
private decimal consensusPriceField;
private bool consensusPriceFieldSpecified;
private decimal compositePriceField;
private bool compositePriceFieldSpecified;
private decimal reconstitutedForwardField;
private bool reconstitutedForwardFieldSpecified;
private decimal consensusVolField;
private bool consensusVolFieldSpecified;
private decimal compositeVolField;
private bool compositeVolFieldSpecified;
private string priceOutField;
private decimal priceRangeField;
private bool priceRangeFieldSpecified;
private decimal priceStddevField;
private bool priceStddevFieldSpecified;
private string volOutField;
private decimal volRangeField;
private bool volRangeFieldSpecified;
private decimal volStddevField;
private bool volStddevFieldSpecified;
private string contributorsField;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 0)]
public decimal price
get
return this.priceField;
set
this.priceField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 1)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool priceSpecified
get
return this.priceFieldSpecified;
set
this.priceFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 2)]
public decimal forward
get
return this.forwardField;
set
this.forwardField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 3)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool forwardSpecified
get
return this.forwardFieldSpecified;
set
this.forwardFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 4)]
public decimal vol
get
return this.volField;
set
this.volField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 5)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool volSpecified
get
return this.volFieldSpecified;
set
this.volFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 6)]
public decimal consensusPrice
get
return this.consensusPriceField;
set
this.consensusPriceField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 7)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool consensusPriceSpecified
get
return this.consensusPriceFieldSpecified;
set
this.consensusPriceFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 8)]
public decimal compositePrice
get
return this.compositePriceField;
set
this.compositePriceField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 9)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool compositePriceSpecified
get
return this.compositePriceFieldSpecified;
set
this.compositePriceFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 10)]
public decimal reconstitutedForward
get
return this.reconstitutedForwardField;
set
this.reconstitutedForwardField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 11)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool reconstitutedForwardSpecified
get
return this.reconstitutedForwardFieldSpecified;
set
this.reconstitutedForwardFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 12)]
public decimal consensusVol
get
return this.consensusVolField;
set
this.consensusVolField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 13)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool consensusVolSpecified
get
return this.consensusVolFieldSpecified;
set
this.consensusVolFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 14)]
public decimal compositeVol
get
return this.compositeVolField;
set
this.compositeVolField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 15)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool compositeVolSpecified
get
return this.compositeVolFieldSpecified;
set
this.compositeVolFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 16)]
public string priceOut
get
return this.priceOutField;
set
this.priceOutField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 17)]
public decimal priceRange
get
return this.priceRangeField;
set
this.priceRangeField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 18)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool priceRangeSpecified
get
return this.priceRangeFieldSpecified;
set
this.priceRangeFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 19)]
public decimal priceStddev
get
return this.priceStddevField;
set
this.priceStddevField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 20)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool priceStddevSpecified
get
return this.priceStddevFieldSpecified;
set
this.priceStddevFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 21)]
public string volOut
get
return this.volOutField;
set
this.volOutField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 22)]
public decimal volRange
get
return this.volRangeField;
set
this.volRangeField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 23)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool volRangeSpecified
get
return this.volRangeFieldSpecified;
set
this.volRangeFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 24)]
public decimal volStddev
get
return this.volStddevField;
set
this.volStddevField = value;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Order = 25)]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool volStddevSpecified
get
return this.volStddevFieldSpecified;
set
this.volStddevFieldSpecified = value;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order =26)]
public string contributors
get
return this.contributorsField;
set
this.contributorsField = value;
【问题讨论】:
【参考方案1】:我在实体类中的每个属性之上使用了 XmlElement[Order =n]。所以,在玩弄了排序之后,我可以使这个序列化工作。继承和部分类使这个修复变得更加困难!谢谢。
【讨论】:
【参考方案2】:XmlSerializer 按类中的声明顺序生成元素 - 你能改变实体中的顺序吗?
【讨论】:
我做到了。但行为仍然相同。谢谢。 您能否将类定义和序列化的 XML 添加到您的问题中,以便我们了解更多细节? 好的。只是一个简单的问题。Order 属性值是从 0 开始还是从 1 开始?谢谢。 如果它像 DataMember 一样工作(我怀疑它会这样),那么确切的值并不重要 - 较高的值在较低的值之后 好的..我从 1 开始给了订单,它给了我一个错误,说“在序列化过程中有一个错误反映属性'项目'”。所以我认为可能是订单从 0 开始。无论如何,我现在尝试将 order 设置为 0。谢谢【参考方案3】:如何将Order = N
与其他 XML 属性和 List 集合一起使用。
public class MyClass
[XmlAnyElement("My-XLMComment", Order = 3)] public XmlComment CommentA get; set; = new XmlDocument().CreateComment("This is an XML comment");
[XmlAttribute("MyAttribute")] public string str4 get; set; //This is a XML-Attribute, Order not applicable
[XmlIgnore] public string str1 get; set; //This is a [XmlIgnore], Order not applicable
[XmlElement(Order = 5)] public string str2 get; set; // Standard property with Order
[XmlElement(Order = 2)] public string str3 get; set; // Standard property with Order
[XmlElement(Order = 1)] public List<MyList> ListElms = new List<MyList> //List collection with Order
new ListElm str1 = "xxx", str2 ="yyy", str3 ="zzz" ,
new ListElm str1 = "xxx", str2 ="yyy", str3 ="zzz"
;
public class MyList
[XmlElement(Order = 3)] public string str1 get; set; // Order can be assigned, but not mandatory
[XmlElement(Order = 2)] public string str2 get; set; // Order can be assigned, but not mandatory
[XmlElement(Order = 1)] public string str3 get; set; // Order can be assigned, but not mandatory
将序列化为:
<MyClass MyAttribute="str4">
<ListElms>
<str3>zzz</str3>
<str2>yyy</str2>
<str1>xxx</str1>
</ListElms>
<ListElms>
<str3>zzz</str3>
<str2>yyy</str2>
<str1>xxx</str1>
</ListElms>
<str3>str3</str3>
<!--This is an XML comment-->
<str2>str2</str2>
</MyClass>
【讨论】:
以上是关于以编程方式控制 xml 元素的顺序的主要内容,如果未能解决你的问题,请参考以下文章