【问题标题】:Any way to override how <choice> element is binded by xsd.exe覆盖 xsd.exe 如何绑定 <choice> 元素的任何方式
【发布时间】:2010-04-15 15:27:44
【问题描述】:

我的架构中有以下元素:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="optimizeModelBase">
    <xs:attribute name="name" type="xs:string"/>
  </xs:complexType>

  <xs:complexType name="riskModel">
    <xs:complexContent>
      <xs:extension base="optimizeModelBase">
        <xs:attribute name="type" type="xs:string" use="required"/>        
      </xs:extension>      
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="fullCovariance">
    <xs:complexContent>
      <xs:extension base="optimizeModelBase">
        <xs:attribute name="fromDate" type="xs:date" use="required"/>
        <xs:attribute name="toDate" type="xs:date" use="required"/>
        <xs:attribute name="windowSize" type="xs:int" use="required"/>
      </xs:extension>
    </xs:complexContent>    
  </xs:complexType>

在我的主要模式主体中,我使用一个元素来指定一种情况:

<xs:choice id="RiskModelParameter">
  <xs:element name="RiskModel" type="riskModel"/>
  <xs:element name="FullCovariance" type="fullCovariance"/>
</xs:choice>

当我运行 xsd.exe 时,生成的代码是:

    [System.Xml.Serialization.XmlElementAttribute("FullCovariance",
    typeof(fullCovariance))]
    [System.Xml.Serialization.XmlElementAttribute("RiskModel", 
    typeof(riskModel))]
    public optimizeModelBase Item 
    {
        get 
        {
           return this.itemField;
        } 
        set 
        {
            this.itemField = value;
        }
    }

问题是元素的 ID 标签被忽略,xsd.exe 任意命名属性“Item”。我不得不承认,这不是一个大问题,但它开始让我烦恼。让这更烦人的是,如果我在同一级别有其他元素,xsd.exe 会将它们绑定为“Item1”、“Item2”等。

有谁知道是否有可能让 xsd.exe 将我的选择元素命名为“项目”,而是能够放入我自己的属性名称?

【问题讨论】:

    标签: xsd xsd.exe


    【解决方案1】:

    我搜索了高低,但似乎没有解决我的问题。根据链接:

    http://msdn.microsoft.com/en-us/library/sa6z5baz(VS.80).aspx 似乎选择元素的任意命名是 not 可覆盖的。希望这些信息对其他人有所帮助......!

    【讨论】:

      【解决方案2】:

      今天刚好遇到这个问题。

      我确实有一个解决方法,因此您可以使用组而不是选择来规避这个问题。

      以上述xsd为基础:

      重写:

      <xs:choice id="RiskModelParameter">
        <xs:element name="RiskModel" type="riskModel"/>
        <xs:element name="FullCovariance" type="fullCovariance"/>
      </xs:choice>
      

      收件人:

      <xs:group name="RiskModelGroup">
          <xs:sequence>
              <xs:element name="RiskModel" type="riskModel"/>
              <xs:element name="FullCovariance" type="fullCovariance"/>
          </xs:sequence>
      </xs:group>
      

      在您的元素中引用组:

      <xs:element name="Foo">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="SomeFieldId" type="xs:int" />
            <xs:group ref="RiskModelGroup" minOccurs="1" maxOccurs="1"/>
          </xs:sequence>
          </xs:complexType>
      </xs:element>
      

      运行xsd.exe,结果如下

      public partial class Foo {
      
          private int someFieldIdField;
      
          private riskModel riskModelField;
      
          private fullCovariance fullCovarianceField;
      
          /// <remarks/>
          public int SomeFieldId {
              get {
                  return this.someFieldIdField;
              }
              set {
                  this.someFieldIdField = value;
              }
          }
      
          /// <remarks/>
          public riskModel RiskModel {
              get {
                  return this.riskModelField;
              }
              set {
                  this.riskModelField = value;
              }
          }
      
          /// <remarks/>
          public fullCovariance FullCovariance {
              get {
                  return this.fullCovarianceField;
              }
              set {
                  this.fullCovarianceField = value;
              }
          }
      }
      

      现在您有了属性名称 RiskModel 和 FullCovariance

      Foo f = new Foo()
      f.RiskModel.name
      

      f.FullCovariance.fromDate
      

      如果您需要多个 RiskModel 项和 FullCovariance 对象,您可以在一个序列中添加一个具有 RiskModelGroup 的新元素。

      祝你好运!

      【讨论】:

      • 谢谢,但我真的只需要发送一个或另一个 xml 节点。服务器端根据xml的形式做一个切换。所以发送两个节点(即使一个是 nilled)是行不通的。
      【解决方案3】:

      对于那些仍然想知道的人:只需使用 XSDObjectGenerator(由 Microsoft 制造)。它通过为您的类中的每个选择添加一个对象来管理 XsdChoice。这样,您不必为 Item 属性寻找正确的元素。 例如:

      <xs:complexType name="AccountSchemeName1Choice">
          <xs:sequence>
              <xs:choice>
                  <xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
                  <xs:element name="Prtry" type="Max35Text"/>
              </xs:choice>
          </xs:sequence>
      </xs:complexType>
      

      变成了

      [XmlType(TypeName = "AccountSchemeName1Choice", Namespace = Declarations.SchemaVersion), Serializable]
      public class AccountSchemeName1Choice : INotifyPropertyChanged
      {
      
          [XmlElement(ElementName = "Cd", IsNullable = false, Form = XmlSchemaForm.Qualified, DataType = "string", Namespace = Declarations.SchemaVersion)]
          public string __Cd;
      
          [XmlIgnore]
          public string Cd
          {
              get { return __Cd; }
              set { __Cd = value; RaisePropertyChanged("Cd"); }
          }
      
          [XmlElement(ElementName = "Prtry", IsNullable = false, Form = XmlSchemaForm.Qualified, DataType = "string", Namespace = Declarations.SchemaVersion)]
          public string __Prtry;
      
          [XmlIgnore]
          public string Prtry
          {
              get { return __Prtry; }
              set { __Prtry = value; RaisePropertyChanged("Prtry"); }
          }
      
          public AccountSchemeName1Choice()
          {
          }
      
          [field: NonSerialized]
          public event PropertyChangedEventHandler PropertyChanged;
          private void RaisePropertyChanged(string propertyName)
          {
              if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
          }
      }
      

      【讨论】:

        【解决方案4】:

        我曾经实际解析过一个自动生成的 xsd.exe 文件并使用 NRefactory 对其进行了更改。

        【讨论】:

          【解决方案5】:

          我自己在处理 XSD.exe 时遇到了这个限制。对于 XSD.exe 如何解释所有元素类型的 ID 属性,这似乎是一种相当统一的做法。我很想听听 MS 开发团队中有人解释为什么 XSD.exe 以这种方式工作。

          有趣的是,我一直在研究 SchemaImporterExtension,除其他外,它会利用选择元素的 ID 属性来精确实现您所描述的内容,这是一种自定义选择映射对象的字段/属性名称的方法成员。

          不幸的是,XSD.exe 不仅看起来不支持 ID 属性绑定,而且在反映解析的架构文档中的选择元素的 XmlSchemaChoice 对象中甚至没有出现 ID。

          也许我遗漏了一些东西,但如果这确实是预期的行为而不是我的错误,那么在我的估计中这是一个非常荒谬的遗漏,它说明了多少中性 XSD 表示被反映在 MS 架构自动生成工具中。

          XSD.exe 遵循我所说的对 XML 模式标准的“精益求精”的解释。显然现在 WCF 消除了 XSD.exe,你猜怎么着? WCF 的 svcutil 工具可以识别更更小的 XML 模式足迹; svcutil IIRC 甚至不支持选择元素绑定。

          在某些时候,我什至不确定 MS 自动生成工具会带来什么价值,因为您将不得不使用琐碎的 XSD 结构(我的意思是,没有选择元素支持?真的吗?)来封装您的业务对象建模。

          【讨论】:

          • 文字墙!不完全清楚这是否回答了这个问题。我建议你添加一些格式、段落、标题等以使其更具可读性
          • 格式化了文字墙以便我可以阅读它,所以在这里
          猜你喜欢
          • 2011-11-15
          • 2011-11-30
          • 1970-01-01
          • 2017-11-09
          • 1970-01-01
          • 2017-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多