很早以前看过一句话:“XML就象空气”,在企业应用开发中XML是一个重要的数据交换标准。而XSD则可以用来校验XML的数据格式是否正确。
一个典型的XSD文件如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- edited with XMLSpy v2013 (http://www.altova.com) by () --> 3 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 4 <xs:element name="AWB"> 5 <xs:annotation> 6 <xs:documentation>运单</xs:documentation> 7 </xs:annotation> 8 <xs:complexType> 9 <xs:sequence> 10 <xs:element name="AWB-INFO" minOccurs="1" maxOccurs="1"> 11 <xs:complexType> 12 <xs:sequence> 13 <xs:element name="AWBPRE"> 14 <xs:annotation> 15 <xs:documentation>运单前缀只有输入3位数字</xs:documentation> 16 </xs:annotation> 17 <xs:simpleType> 18 <xs:restriction base="xs:positiveInteger"> 19 <xs:totalDigits value="3"/> 20 </xs:restriction> 21 </xs:simpleType> 22 </xs:element> 23 <xs:element name="AWBNO"> 24 <xs:annotation> 25 <xs:documentation>运单号只能输入8位数字</xs:documentation> 26 </xs:annotation> 27 <xs:simpleType> 28 <xs:restriction base="xs:positiveInteger"> 29 <xs:totalDigits value="8"/> 30 </xs:restriction> 31 </xs:simpleType> 32 </xs:element> 33 </xs:sequence> 34 </xs:complexType> 35 </xs:element> 36 <xs:element name="PART-INFO"> 37 <xs:complexType> 38 <xs:sequence> 39 <xs:element name="PARTICIPANT" minOccurs="2" maxOccurs="unbounded"> 40 <xs:annotation> 41 <xs:documentation>物流参与者至少要有2个</xs:documentation> 42 </xs:annotation> 43 <xs:complexType> 44 <xs:sequence> 45 <xs:element name="TYPE"> 46 <xs:annotation> 47 <xs:documentation>物流参考者类型,只能是A/S/C其中之一</xs:documentation> 48 </xs:annotation> 49 <xs:simpleType> 50 <xs:restriction base="xs:string"> 51 <xs:enumeration value="C"/> 52 <xs:enumeration value="S"/> 53 <xs:enumeration value="A"/> 54 </xs:restriction> 55 </xs:simpleType> 56 </xs:element> 57 <xs:element name="ADDRESS" type="AddressType"/> 58 </xs:sequence> 59 </xs:complexType> 60 </xs:element> 61 </xs:sequence> 62 </xs:complexType> 63 </xs:element> 64 </xs:sequence> 65 </xs:complexType> 66 </xs:element> 67 <xs:complexType name="AddressType"> 68 <xs:sequence> 69 <xs:element name="Name" type="xs:string"/> 70 <xs:element name="Street" type="xs:string"/> 71 <xs:element name="City" type="xs:string"/> 72 </xs:sequence> 73 </xs:complexType> 74 </xs:schema>
看到这一大段xml,第一反应通常是头晕,幸好这些内容不用纯手动编写,已经有很多现成的工具,比如XmlSpy可以方便的以GUI方式,通过轻点鼠标,拖拖拉拉就能完成XSD的开发。
这是XmlSpy中XSD的可视化设计界面,还能切换不同的视图,比如下面这样:
对于首次接触XmlSpy的朋友,强烈推荐看下安装目录下的Tutorial.pdf,这是一个不错的入门教程,30分钟以前绝对可以快速浏览一遍。
C#中可以方便的使用XSD来验证xml文件的正确性,示例代码如下:
1 using System; 2 using System.Xml; 3 4 namespace XsdValidate 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 string xmlFile = @"C:\Users\jimmy.yang\Desktop\XMLSPY\TEST\sample.xml"; 11 string xsdFile = @"C:\Users\jimmy.yang\Desktop\XMLSPY\TEST\sample.xsd"; 12 13 var xsdValidateResult = ValidateXml(xmlFile, xsdFile); 14 15 if (xsdValidateResult.Item1) 16 { 17 Console.WriteLine("校验通过!"); 18 } 19 else 20 { 21 Console.WriteLine("校验失败,原因:\n" + xsdValidateResult.Item2); 22 } 23 Console.Read(); 24 25 } 26 27 /// <summary> 28 /// 使用xsd验证xml是否正确 29 /// </summary> 30 /// <param name="xmlFilePath">xml文件路径</param> 31 /// <param name="xsdFilePath">xsd文件路径</param> 32 /// <returns></returns> 33 static Tuple<bool, string> ValidateXml(string xmlFilePath, string xsdFilePath) 34 { 35 Tuple<bool, string> result = new Tuple<bool, string>(true, ""); 36 XmlReaderSettings st = new XmlReaderSettings(); 37 st.ValidationType = ValidationType.Schema; 38 st.Schemas.Add(null, xsdFilePath); 39 40 //设置验证xml出错时的事件。 41 st.ValidationEventHandler += (obj, e) => 42 { 43 result = new Tuple<bool, string>(false, e.Message); 44 }; 45 46 XmlReader xr = XmlReader.Create(xmlFilePath, st); 47 while (xr.Read()) 48 { 49 if (xr.IsStartElement()) 50 { 51 xr.Read(); 52 } 53 } 54 xr.Close(); 55 return result; 56 } 57 } 58 }
注意:如果节点采用pattern,即正则表达式验证,比如
<xs:restriction base="xs:string">
<xs:pattern value="^\d{8}$"></xs:pattern>
</xs:restriction>
XMLSpy中,该节点必须填写"^12345678$"才能验证通过,而如果用.NET/JAVA写代码验证的话,^、$能自动识别为"匹配字符开头/结尾"
XSD还能方便的生成c#类,有二种方法:
1、XMLSpy里先打开一个XSD文件,然后 DTD/Schema->Generate Program Code,接下来按提示操作即可
注:XMLSpy生成的c#类太过于复杂,我个人觉得有点啰嗦
2、直接使用vs.net自带的xsd命令
vs.net命令行下,输入
xsd "xsd文件所在的路径" /classes /out:"cs文件的输出目录"
即可生成对应的cs类 ,文中最开头的xsd生成的cs类代码如下:
1 //------------------------------------------------------------------------------ 2 // <auto-generated> 3 // This code was generated by a tool. 4 // Runtime Version:4.0.30319.18331 5 // 6 // Changes to this file may cause incorrect behavior and will be lost if 7 // the code is regenerated. 8 // </auto-generated> 9 //------------------------------------------------------------------------------ 10 11 using System.Xml.Serialization; 12 13 // 14 // This source code was auto-generated by xsd, Version=4.0.30319.1. 15 // 16 17 18 /// <remarks/> 19 [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 20 [System.SerializableAttribute()] 21 [System.Diagnostics.DebuggerStepThroughAttribute()] 22 [System.ComponentModel.DesignerCategoryAttribute("code")] 23 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] 24 [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)] 25 public partial class AWB { 26 27 private AWBAWBINFO aWBINFOField; 28 29 private AWBPARTICIPANT[] pARTINFOField; 30 31 /// <remarks/> 32 [System.Xml.Serialization.XmlElementAttribute("AWB-INFO")] 33 public AWBAWBINFO AWBINFO { 34 get { 35 return this.aWBINFOField; 36 } 37 set { 38 this.aWBINFOField = value; 39 } 40 } 41 42 /// <remarks/> 43 [System.Xml.Serialization.XmlArrayAttribute("PART-INFO")] 44 [System.Xml.Serialization.XmlArrayItemAttribute("PARTICIPANT", IsNullable=false)] 45 public AWBPARTICIPANT[] PARTINFO { 46 get { 47 return this.pARTINFOField; 48 } 49 set { 50 this.pARTINFOField = value; 51 } 52 } 53 } 54 55 /// <remarks/> 56 [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 57 [System.SerializableAttribute()] 58 [System.Diagnostics.DebuggerStepThroughAttribute()] 59 [System.ComponentModel.DesignerCategoryAttribute("code")] 60 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] 61 public partial class AWBAWBINFO { 62 63 private string aWBPREField; 64 65 private string aWBNOField; 66 67 /// <remarks/> 68 [System.Xml.Serialization.XmlElementAttribute(DataType="positiveInteger")] 69 public string AWBPRE { 70 get { 71 return this.aWBPREField; 72 } 73 set { 74 this.aWBPREField = value; 75 } 76 } 77 78 /// <remarks/> 79 [System.Xml.Serialization.XmlElementAttribute(DataType="positiveInteger")] 80 public string AWBNO { 81 get { 82 return this.aWBNOField; 83 } 84 set { 85 this.aWBNOField = value; 86 } 87 } 88 } 89 90 /// <remarks/> 91 [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 92 [System.SerializableAttribute()] 93 [System.Diagnostics.DebuggerStepThroughAttribute()] 94 [System.ComponentModel.DesignerCategoryAttribute("code")] 95 public partial class AddressType { 96 97 private string nameField; 98 99 private string streetField; 100 101 private string cityField; 102 103 /// <remarks/> 104 public string Name { 105 get { 106 return this.nameField; 107 } 108 set { 109 this.nameField = value; 110 } 111 } 112 113 /// <remarks/> 114 public string Street { 115 get { 116 return this.streetField; 117 } 118 set { 119 this.streetField = value; 120 } 121 } 122 123 /// <remarks/> 124 public string City { 125 get { 126 return this.cityField; 127 } 128 set { 129 this.cityField = value; 130 } 131 } 132 } 133 134 /// <remarks/> 135 [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 136 [System.SerializableAttribute()] 137 [System.Diagnostics.DebuggerStepThroughAttribute()] 138 [System.ComponentModel.DesignerCategoryAttribute("code")] 139 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] 140 public partial class AWBPARTICIPANT { 141 142 private AWBPARTICIPANTTYPE tYPEField; 143 144 private AddressType aDDRESSField; 145 146 /// <remarks/> 147 public AWBPARTICIPANTTYPE TYPE { 148 get { 149 return this.tYPEField; 150 } 151 set { 152 this.tYPEField = value; 153 } 154 } 155 156 /// <remarks/> 157 public AddressType ADDRESS { 158 get { 159 return this.aDDRESSField; 160 } 161 set { 162 this.aDDRESSField = value; 163 } 164 } 165 } 166 167 /// <remarks/> 168 [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 169 [System.SerializableAttribute()] 170 [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] 171 public enum AWBPARTICIPANTTYPE { 172 173 /// <remarks/> 174 C, 175 176 /// <remarks/> 177 S, 178 179 /// <remarks/> 180 A, 181 }
xsd命令还能直接根据xml生成xsd文件,使用方法如下:
xsd c:\sampe.xml /out:c:\
这样会根据sample.xml在c:\生成sample.xsd文件