【发布时间】:2015-10-10 02:46:32
【问题描述】:
我必须支持需要解析 XML 文件的旧版 Visual Basic 6.0 客户端。这些由相当大且复杂的 XSD 模式描述。为了简化解析过程,我通过 Windows SDK xsd.exe 工具创建了 C# 类,将这些类添加到 C# 库项目中,并设置“Make assembly COM-Visible”属性。不幸的是,生成的类型库没有任何价值,因为它只是为所有复杂类型公开了空接口。
为了说明这种行为,请考虑以下 XSD 架构:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:customers" xmlns:c="urn:customers">
<xsd:element name="catalog" type="c:CatalogData"/>
<xsd:complexType name="AddressData">
<xsd:sequence>
<xsd:element name="no" type="xsd:integer"/>
<xsd:element name="road" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CustomerData">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="address" type="c:AddressData"/>
<xsd:element name="order_date" type="xsd:date"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CatalogData">
<xsd:sequence>
<xsd:element name="customer" type="c:CustomerData" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
xsd 工具创建以下源文件:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.0.30319.33440.
//
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:customers")]
[System.Xml.Serialization.XmlRootAttribute("catalog", Namespace="urn:customers", IsNullable=false)]
public partial class CatalogData {
private CustomerData[] customerField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("customer", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public CustomerData[] customer {
get {
return this.customerField;
}
set {
this.customerField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:customers")]
public partial class CustomerData {
private string nameField;
private AddressData addressField;
private System.DateTime order_dateField;
private string idField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public AddressData address {
get {
return this.addressField;
}
set {
this.addressField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="date")]
public System.DateTime order_date {
get {
return this.order_dateField;
}
set {
this.order_dateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string id {
get {
return this.idField;
}
set {
this.idField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:customers")]
public partial class AddressData {
private string noField;
private string roadField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="integer")]
public string no {
get {
return this.noField;
}
set {
this.noField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string road {
get {
return this.roadField;
}
set {
this.roadField = value;
}
}
}
生成的类型库如下所示:
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: xsd.tlb
[
]
library xsd
{
importlib("mscorlib.tlb");
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface _CatalogData;
interface _CustomerData;
interface _AddressData;
[
]
coclass CatalogData {
[default] interface _CatalogData;
interface _Object;
};
[
]
coclass CustomerData {
[default] interface _CustomerData;
interface _Object;
};
[
]
coclass AddressData {
[default] interface _AddressData;
interface _Object;
};
[
]
interface _CatalogData : IDispatch {
};
[
]
interface _CustomerData : IDispatch {
};
[
]
interface _AddressData : IDispatch {
};
};
我知道,我可以手动创建所需的 COM 接口以公开所有嵌套属性。然而,由于复杂的 XSD 架构,生成的 C# 类文件超过 3000 行,我需要永远为每个部分类创建接口。
是否有替代方案可以加快流程?或者有人知道另一种工具,它可以从 XSD 模式生成 COM 接口/类,最好是通过 ATL 或 C++?
【问题讨论】:
-
这就是 XSD 的全部内容:值类的接口定义的递归包。听起来您真正想要的是一个 XSD 编译器,它可以创建具有 XML 持久性支持的具体类实现,它可以输出 VB6 源代码。由于需求低,不要指望找到免费或便宜的东西,但有人可能已经出版了。搜索出现了这个liquid-technologies.com/xml-data-binding.aspx?view=features
-
同样的服装也发布了codeproject.com/Articles/2299/…,虽然它现在已经很老了,可能不够用。