我尝试使用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识别基类型的属性?