XSD.exe继承属性

时间:2014-06-24 12:38:14

标签: c# xml serialization xsd

我尝试使用XSD.exe针对具有一组所有继承自抽象类的成员的类创建模式文件。我发现虽然抽象类是在模式文件中定义的,但是在根据模式验证XML时,它的属性在派生类型中是不可访问的。

我得到的例外是:

  

"元素' findElement'有无效的子元素'插件'。预期可能元素的列表:' webElement'。"

为了帮助说明,我将提供一些C#代码以及XSD.exe生成的部分模式。

代码 - 派生类型

[Serializable]
public class FindElement : BaseExecutable
{
    private IWebElement _element = null;
    private TimeSpan _waitTimeout;
    private object _option = null;
    private WebElement _webElement = null;

    [XmlChoiceIdentifier("FindElementType")]
    [XmlElement("id", typeof(string))]
    [XmlElement("className", typeof(string))]
    [XmlElement("cssSelector", typeof(string))]
    [XmlElement("linkText", typeof(string))]
    [XmlElement("name", typeof(string))]
    [XmlElement("partialLinkText", typeof(string))]
    [XmlElement("tagName", typeof(string))]
    [XmlElement("xpath", typeof(string))]
    public object Option
    {
        get
        {
            if (this._option is ISDriver)
                (this._option as ISDriver).Root = base.Root;

            return this._option;
        }
        set
        {
            if (value is ISDriver)
                (value as ISDriver).Root = base.Root;

            _option = value;
        }
    }

    [XmlAttribute("useWait")]
    public bool UseWait { get; set; }

    [XmlAttribute("waitTimeout"), DefaultValue(0)]
    public long WaitTimeoutMilliseconds
    {
        get { return (long)_waitTimeout.TotalMilliseconds; }
        set { _waitTimeout = new TimeSpan(value * 10000); }
    }

    [XmlElement("webElement")]
    public WebElement WebElement
    {
        get
        {
            if (this._webElement is ISDriver)
                this._webElement.Root = base.Root;

            return this._webElement;
        }
        set
        {
            if (value is ISDriver)
                (value as ISDriver).Root = base.Root;

            this._webElement = value;
        }
    }

    public FindElement()
    {
        this.WebElement = new WebElement { };
    }
}

代码 - 基本类型

[Serializable]
public abstract class BaseExecutable : ISDriver, ICloneable
{

    private List<Format> _formatters = null;
    private Conditional _conditional = null;

    [XmlAttribute("screenShot"), DefaultValue(ScreenShotType.None)]
    public virtual ScreenShotType ScreenShotType { get; set; }

    [XmlAttribute("screenShotSize"), DefaultValue(ScreenShotSizeType.Tn)]
    public virtual ScreenShotSizeType ScreenShotSizeType { get; set; }

    [XmlAttribute("name")]
    public virtual string Name { get; set; }

    [XmlAttribute("description")]
    public virtual string Description { get; set; }

    [XmlArray("messages")]
    [XmlArrayItem("message")]
    public virtual List<Message> Messages { get; set; }

    [XmlAttribute("message")]
    public string Message { get; set; }

    [XmlAttribute("msgLevel"), DefaultValue(MsgLevelType.Off)]
    public MsgLevelType MsgLevel { get; set; }

    [XmlAttribute("continueOnFail"), DefaultValue(true)]
    public virtual bool ContinueOnFail { get; set; }

    [XmlAttribute("key")]
    public string Key { get; set; }

    [XmlArray("plugins")]
    [XmlArrayItem("plugin")]
    public List<Plugin> Plugins { get; set; }

    [XmlElement("conditional")]
    public Conditional Conditional
    {
        get
        {
            if (this._conditional is ISDriver)
                (this._conditional as ISDriver).Root = this.Root;

            return this._conditional;
        }
        set
        {
            // Just in case we added a type later that doesn't implement ISDriver.
            if (value is ISDriver)
                (value as ISDriver).Root = this.Root;

            _conditional = value;
        }
    }

    [XmlElement("expression")]
    public string Expression { get; set; }

    [XmlArray("formatters")]
    [XmlArrayItem("formatter")]
    public List<Format> Formatters
    {
        get
        {
            foreach (ISDriver f in this._formatters ?? new List<Format>())
                f.Root = this.Root;

            return this._formatters;
        }
        set
        {
            foreach (ISDriver f in value)
                f.Root = this.Root;

            this._formatters = value;
        }
    }

    public BaseExecutable()
    {
        this.ContinueOnFail = false;
        this.Plugins = new List<Plugin>();
    }
}

从继承的角度来看,&#34;插件&#34;是公共的,并且在反序列化时可用于派生类型。但是现在我正在尝试创建一个模式来强制执行XML,我发现XSD.exe没有发出一个识别基类属性的定义。

XSD架构 - 派生类型

<xs:complexType name="FindElement">
  <xs:complexContent mixed="false">
    <xs:extension base="BaseExecutable">
      <xs:sequence>
        <xs:choice minOccurs="1" maxOccurs="1">
          <xs:element minOccurs="0" maxOccurs="1" name="cssSelector" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="xpath" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="className" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="linkText" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="id" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="name" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="tagName" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="partialLinkText" type="xs:string" />
        </xs:choice>
        <xs:element minOccurs="0" maxOccurs="1" name="webElement" type="WebElement" />
      </xs:sequence>
      <xs:attribute name="useWait" type="xs:boolean" use="required" />
      <xs:attribute default="0" name="waitTimeout" type="xs:long" />
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

XSD架构 - 基本类型

<xs:complexType name="BaseExecutable">
  <xs:sequence>
    <xs:element minOccurs="0" maxOccurs="1" name="messages" type="ArrayOfMessage" />
    <xs:element minOccurs="0" maxOccurs="1" name="plugins" type="ArrayOfPlugin" />
    <xs:element minOccurs="0" maxOccurs="1" name="conditional" type="Conditional" />
    <xs:element minOccurs="0" maxOccurs="1" name="expression" type="xs:string" />
    <xs:element minOccurs="0" maxOccurs="1" name="formatters" type="ArrayOfFormat" />
  </xs:sequence>
  <xs:attribute default="none" name="screenShot" type="ScreenShotType" />
  <xs:attribute default="tn" name="screenShotSize" type="ScreenShotSizeType" />
  <xs:attribute name="name" type="xs:string" />
  <xs:attribute name="description" type="xs:string" />
  <xs:attribute name="message" type="xs:string" />
  <xs:attribute default="off" name="msgLevel" type="MsgLevelType" />
  <xs:attribute default="true" name="continueOnFail" type="xs:boolean" />
  <xs:attribute name="key" type="xs:string" />
</xs:complexType>

测试XML文件

<sDriver xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" msgLevel="info">
 <packages>
   <package packageName="Google Test">
     <drivers>
       <driver>
         <actions>
           <action screenShot="after">
             <navigate>
               <gotToUrl Url="https://www.google.com/" msgLevel="info" />
             </navigate>
           </action>
           <action name="actionTitleElement" screenShot="after">
             <findElement useWait="false" msgLevel="info">
               <xpath>/html/head/title</xpath>
               <plugins>
                 <plugin name="Custom.Plugin" />
               </plugins>
             </findElement>
           </action>
         </actions>
       </driver>
     </drivers>
   </package>
 </packages>

有没有办法手动更改架构,或者使用XSD.exe识别基类型的属性?

0 个答案:

没有答案