项目中有时候要用XML作为数据源,因此需要定义XML文件和相应的类,最佳方法是首先定义XSD,然后自动生成实体类,最后生成XML和填充数据;读取XML数据源的时候,首先用XSD验证XML数据格式,然后自动读入实体类使用。 定义XSD的过程就是类似设计表结构的过程,二者也可以相互转化。 本文讨论了如何定义XSD文件(XML Schema),然后自动生成实体类,最后生成XML的过程,以及如何根据XSD验证XML文件的合法性。以供大家做项目时参考。 1.
首先在VS2005 中添加一个XSD 文件。例子XSD 可以参考:
http://www.15seconds.com/issue/031209.htm
http://www.cduce.org/manual_schema_samples.html
2. 使用VS2005 工具XSD.exe (SDK/v2.0/Bin/xsd.exe) 自动生成实体类:
xsd /c /namespace:myCompany /language:CS temp1.xsd
也可以生成DataSet 类型的类:
xsd /dataset /language:CS temp1.xsd
( 类文件和XSD之间可以相互转换,也就是说,你也可以先生成类,然后自动生成XSD)
自动读取XML数据到实体类:
XmlSerializer xs
=
new
XmlSerializer(
typeof
(myClassType));
using
(FileStream fs
=
new
FileStream(XmlFilePath, FileMode.Open))
{ return (myClassType)xs.Deserialize(fs); }
3. 如何由XML 生成XSD ? - 可以用工具,如XMLSpy,首先打开XML, 然后DTD/Schema -> Generate DTD/Schema, 选择W3c Sehcma即可。
- 此方法不一定能生成确切满足需求的XSD,另需修改。
4. 如何由XSD生成XML? - 可以用其他工具,如XMLSpy,DTD/Schema -> Generate sample XML file... - 可以由XSD生成类,然后写代码实例化这个类,最后序列化为XML - 如何自动给类每个属性设置一个空值:(用反射的方法) 代码示例:
/**/
/// <summary> /// Get all properties and set default value /// </summary> /// <typeparam name="T"> Type </typeparam> /// <param name="item"> Object </param>
private
static
void
ReflctProperties
<
T
>
(T item)
{ PropertyInfo[] pty = typeof (T).GetProperties(); Type t = item.GetType(); if (pty != null ) { foreach (PropertyInfo info in pty) { if ( ! info.CanWrite) continue ; if (info.PropertyType == typeof (String)) { t.GetProperty(info.Name).SetValue(item, String.Empty, null ); } if (info.PropertyType == typeof (Boolean)) { t.GetProperty(info.Name).SetValue(item, true , null ); } } } }
- 反射读取类的属性:
public
static
object
GetProperty
<
T
>
(T item,
string
PropertyName)
{ PropertyInfo propertyInfo = item.GetType().GetProperty(PropertyName); if (propertyInfo != null ) { return propertyInfo.GetValue(item, null ); } return null ; }
- 如何序列化为XML?
/**/
/// <summary> /// Serialize class instance to XML file /// </summary> /// <typeparam name="T"> type </typeparam> /// <param name="XMLFileToCreate"> XMLFileToCreate </param> /// <param name="instance"> class instance </param>
public
void
Serialize
<
T
>
(
string
XMLFileToCreate, T instance)
{ if (instance == null ) return ; XmlSerializer xs = new XmlSerializer( typeof (T)); using (StreamWriter sw = new StreamWriter(XMLFileToCreate)) { xs.Serialize(sw, instance); } }
(Link: 使用XMLSerializer类持久化数据 )
5. 如何使用XSD来验证
XML 文件合法性:
- 使用XMLSpy,首先Assign XSD,然后验证 (其实就是设置XML里面引用的schema,注意schema可能引用其他的schema)
- 代码中验证:
Validate XML against XSD
#region Validate XML against XSD public class Validator { private string errMsg; /**/ /// <summary> /// validation Error Msg /// </summary> public string validationErrMsg { get { return errMsg; } set { errMsg = value; } } /**/ /// <summary> /// Validate XML against schema /// </summary> /// <param name="XSD"></param> /// <param name="XMLFile"></param> /// <param name="LocationDefined"></param> /// <returns></returns> public bool Validate( string XSD, string XMLFile, bool LocationDefined) { bool isValid = true ; try { Stream schemaFile = null ; XmlReaderSettings settings = new XmlReaderSettings(); ValidationEventHandler SchemaValidationEventHandler = new ValidationEventHandler(ValidationCallBack); settings.ValidationType = ValidationType.Schema; settings.ValidationFlags |= XmlSchemaValidationFlags.AllowXmlAttributes; settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; settings.ValidationEventHandler += SchemaValidationEventHandler; if (LocationDefined == true ) { settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; } else { schemaFile = new FileStream(XSD, FileMode.Open); XmlSchema tmsSchema = XmlSchema.Read(schemaFile, SchemaValidationEventHandler); settings.Schemas.Add(tmsSchema); } using (XmlReader reader = XmlReader.Create(XMLFile, settings)) { string test; while (reader.Read() && isValid == true ) { test = reader.Name; } }; if (schemaFile != null ) { schemaFile.Close(); } } catch (Exception e) { validationErrMsg += " Exception occured when validating. " + e.Message; isValid = false ; } return isValid; } /**/ /// <summary> /// Display any warnings or errors. /// </summary> /// <param name="sender"></param> /// <param name="args"></param> public void ValidationCallBack( object sender, ValidationEventArgs args) { if (args.Severity == XmlSeverityType.Warning) { validationErrMsg += " Matching schema not found. No validation occurred. " + args.Message; validationErrMsg = args.Message; } else { validationErrMsg += " /nValidation error: " + args.Message; validationErrMsg = args.Message; } } } #endregion