XmlSpy中创建XSD以及利用XSD验证验证XML文件
很早以前看过一句话:“XML就象空气”,在企业应用开发中XML是一个重要的数据交换标准。而XSD则可以用来校验XML的数据格式是否正确。
一个典型的XSD文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!-- edited with XMLSpy v2013 (http://www.altova.com) by () --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="AWB"> <xs:annotation> <xs:documentation>运单</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="AWB-INFO" minOccurs="1" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="AWBPRE"> <xs:annotation> <xs:documentation>运单前缀只有输入3位数字</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="xs:positiveInteger"> <xs:totalDigits value="3"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="AWBNO"> <xs:annotation> <xs:documentation>运单号只能输入8位数字</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="xs:positiveInteger"> <xs:totalDigits value="8"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="PART-INFO"> <xs:complexType> <xs:sequence> <xs:element name="PARTICIPANT" minOccurs="2" maxOccurs="unbounded"> <xs:annotation> <xs:documentation>物流参与者至少要有2个</xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="TYPE"> <xs:annotation> <xs:documentation>物流参考者类型,只能是A/S/C其中之一</xs:documentation> </xs:annotation> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="C"/> <xs:enumeration value="S"/> <xs:enumeration value="A"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="ADDRESS" type="AddressType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="AddressType"> <xs:sequence> <xs:element name="Name" type="xs:string"/> <xs:element name="Street" type="xs:string"/> <xs:element name="City" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema>
看到这一大段xml,第一反应通常是头晕,幸好这些内容不用纯手动编写,已经有很多现成的工具,比如XmlSpy可以方便的以GUI方式,通过轻点鼠标,拖拖拉拉就能完成XSD的开发。
设计XSD时可采用多重设计视图,其中最常用的是Schema视图,此外,Grid和XML两种视图可视随时查看设计结果。如下图所示。
这是XmlSpy中XSD的可视化设计界面,还能切换不同的视图,比如下面这样:
对于首次接触XmlSpy的朋友,强烈推荐看下安装目录下的Tutorial.pdf,这是一个不错的入门教程,30分钟以前绝对可以快速浏览一遍。
设计XSD的总体思路是:
(1)先在Schema设计视图设计复杂元素,即xs:complexType类型的元素,这些复杂元素一般都是由简单元素xs:simpleType构成的,定义好的复杂元素可以同简单类型一样作为新的类型使用。
(2)接着设计整个XML文件的根节点,以及根节点下面的头结点、体结点等结点,以及三、四级等节点。一般都是通过选中相应的父节点,然后选择:Insert-Element菜单项。对于每一个节点,还可以为其设计属性,通过选择:Insert-Attribute菜单项。注意,还可以在右侧的Details可停靠窗口为每一个节点设计细节等参数,如可取值的最小/大值,取值类型等。
(3)设计完XSD后,可以在xmlspy环境中用xsd验证xml是否符合设计约束。详细操作参见:XMLSpy怎样通过XSD校验XML
此外,还可以在C#代码中可以方便的使用XSD来验证xml文件的正确性,示例代码如下:
using System; using System.Xml; namespace XsdValidate { class Program { static void Main(string[] args) { string xmlFile = @"C:\Users\jimmy.yang\Desktop\XMLSPY\TEST\sample.xml"; string xsdFile = @"C:\Users\jimmy.yang\Desktop\XMLSPY\TEST\sample.xsd"; var xsdValidateResult = ValidateXml(xmlFile, xsdFile); if (xsdValidateResult.Item1) { Console.WriteLine("校验通过!"); } else { Console.WriteLine("校验失败,原因:\n" + xsdValidateResult.Item2); } Console.Read(); } /// <summary> /// 使用xsd验证xml是否正确 /// </summary> /// <param name="xmlFilePath">xml文件路径</param> /// <param name="xsdFilePath">xsd文件路径</param> /// <returns></returns> static Tuple<bool, string> ValidateXml(string xmlFilePath, string xsdFilePath) { Tuple<bool, string> result = new Tuple<bool, string>(true, ""); XmlReaderSettings st = new XmlReaderSettings(); st.ValidationType = ValidationType.Schema; st.Schemas.Add(null, xsdFilePath); //设置验证xml出错时的事件。 st.ValidationEventHandler += (obj, e) => { result = new Tuple<bool, string>(false, e.Message); }; XmlReader xr = XmlReader.Create(xmlFilePath, st); while (xr.Read()) { if (xr.IsStartElement()) { xr.Read(); } } xr.Close(); return result; } } }
注意:如果节点采用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类代码如下:
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // Runtime Version:4.0.30319.18331 // // 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.1. // /// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)] public partial class AWB { private AWBAWBINFO aWBINFOField; private AWBPARTICIPANT[] pARTINFOField; /// <remarks/> [System.Xml.Serialization.XmlElementAttribute("AWB-INFO")] public AWBAWBINFO AWBINFO { get { return this.aWBINFOField; } set { this.aWBINFOField = value; } } /// <remarks/> [System.Xml.Serialization.XmlArrayAttribute("PART-INFO")] [System.Xml.Serialization.XmlArrayItemAttribute("PARTICIPANT", IsNullable=false)] public AWBPARTICIPANT[] PARTINFO { get { return this.pARTINFOField; } set { this.pARTINFOField = value; } } } /// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] public partial class AWBAWBINFO { private string aWBPREField; private string aWBNOField; /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(DataType="positiveInteger")] public string AWBPRE { get { return this.aWBPREField; } set { this.aWBPREField = value; } } /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(DataType="positiveInteger")] public string AWBNO { get { return this.aWBNOField; } set { this.aWBNOField = value; } } } /// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] public partial class AddressType { private string nameField; private string streetField; private string cityField; /// <remarks/> public string Name { get { return this.nameField; } set { this.nameField = value; } } /// <remarks/> public string Street { get { return this.streetField; } set { this.streetField = value; } } /// <remarks/> public string City { get { return this.cityField; } set { this.cityField = value; } } } /// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] public partial class AWBPARTICIPANT { private AWBPARTICIPANTTYPE tYPEField; private AddressType aDDRESSField; /// <remarks/> public AWBPARTICIPANTTYPE TYPE { get { return this.tYPEField; } set { this.tYPEField = value; } } /// <remarks/> public AddressType ADDRESS { get { return this.aDDRESSField; } set { this.aDDRESSField = value; } } } /// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] [System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] public enum AWBPARTICIPANTTYPE { /// <remarks/> C, /// <remarks/> S, /// <remarks/> A, }
xsd命令还能直接根据xml生成xsd文件,使用方法如下:
xsd c:\sampe.xml /out:c:\
这样会根据sample.xml在c:\生成sample.xsd文件。
参考链接:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理