分享我的DTD与Schema学习笔记
分享下我最近学习DTD与Schema的学习心得,纯属个人总结,如有错误请留言指正:
DTD内部声明:
<!DOCTYPE book [
<!-- DTD声明部分 -->
]>
book是xml根节点
DTD外部声明:
<!ELEMENT 元素名 (子元素1*,子元素2+,子元素3?,子元素4)>
...
xml内引用:
<!DOCTYPE note SYSTEM "note.dtd">
note是XML根节点,
SYSTEM是DTD文件是系统内部应用还是PUBLIC对外公开
“note.dtd”是DTD文件路径
属性声明:
<!ATTLIST 元素名 属性名 属性类型 默认值>
DTD示例:
<!ATTLIST payment type CDATA "check">
XML示例:
<payment type="check" />
属性类型:
CDATA: 不需要解析就能原样显示的字符数据
("男"|"女"):枚举类型
ID: 唯一的ID
IDREF: 引用一个唯一的ID值
IDREFS: 引用ID列表
NMTOKEN: XML名称
NMTOKENS: XML名称列表
ENTITY: 实体
ENTITYS: 实体列表
NOTATION: 符号名称
xml: 一个预定义的XML值
默认值参数:
#REQUIRED 必须的
#IMPLIED 可选的
#FIXED 固定值
内部实体声明:
<!ENTITY 实体名称 "实体值">
DTD 例子:
<!ENTITY name "张三">
外部实体声明:
<!ENTITY 实体名称 实体值>
XML中采用&实体名称;方式引用
内部DTD声明:
<!DOCTYPE XML根节点 [
//这里是元素 、属性、实体的声明部分
<!ENTITY.....
<!ELEMENT.....
<!ATTLIST......
]>
外部DTD声明:
把元素 、属性、实体的声明部分独立到一个DTD文件即可,
举个例子:
<?xml version="1.0" encoding="UTF-8"?>
//这里是元素 、属性、实体的声明部分
<!ENTITY.....
<!ELEMENT.....
<!ATTLIST......
然后XML头部导入外部的DTD文件:
举个例子:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XML根节点 SYSTEM "DTD文件路径">
//下面是XMl正文部分
......省
js验证XML:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.validateOnParse = "true";
xmlDoc.load("??.xml");
xmlDoc.parseError.errorCode 错误码
xmlDoc.parseError.reason 错误原因
xmlDoc.parseError.line 错误行号
Schema常用数据类型:
xs:string 字符串类型
xs:normalizedString XML解析器会处理换行 回车 制表符
xs:token xml解析器会处理换行 回车 制表符 开头结尾的空格中间连续的空格
xs:integer 整型
xs:positiveInteger 正整型
xs:long 64位整数
xs:float 单精度浮点数
xs:double 双精度浮点数
xs:decimal 十进制数字类型 最多18位
xs:boolean 布尔类型 true/false 或1/0
xs:date 日期类型 YYYY-MM-DD
xs:time 时间类型 hh:mm:ss
xs:datetime 日期时间类型 YYYY-MM-DDThh:mm:ss 如2011-11-11T17:10:11
xs:base64Binary base64编码的二进制数据
xs:hexBinary 16进制编码的二进制数据
xs:anyURI uri数据,如http://。。。/images/smiley.gif,uri中有空格请用%20 代替
简单元素定义:(注意简单元素是不能拥有属性,也没有子元素,即类似于这种结构:<a>中间就是数据,没有属性也没有子元素</a>)
<xs:element name="元素名称" type="元素数据类型"/>
一个例子:
<xs:element name="job" type="xs:string"/>
简单元素含默认:
<xs:element name="元素名称" type="元素数据类型" default="默认值"/>
一个例子:
<xs:element name="sex" type="xs:string" default="male"/>
简单元素固定值(类似于常量)
<xs:element name="元素名称" type="元素数据类型" fixed="固定值">
一个例子:
<xs:element name="color" type="xs:string" fixed="red"/>
属性定义:
<xs:attribute name="属性名称" type="属性数据类型"/>
一个例子:
<xs:attribute name="birth" type="xs:date"/>
属性定义有默认值:
<xs:attribute name="属性名称" type="属性数据类型" default="默认值"/>
一个例子:
<xs:attribute name="birth" type="xs:date" default="2011-12-17"/>
属性定义固定值:
<xs:attribute name="属性名称" type="属性数据类型" fixed="固定值"/>
一个例子:
<xs:attribute name="isFirst" type="xs:boolean" fixed="true"/>
属性可选或必选:
<xs:attribute name="属性名称" type="属性数据类型" use="required"/>
required表示必选,缺省情况下是可选
元素值限定:
<xs:restriction base="数据类型">
<xs:minInclusive value="最小值"/>
<xs:maxInclusive value="最大值"/>
</xs:restriction>
一个例子:
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
元素值枚举限定:
<xs:restriction base="数据类型">
<xs:enumeration value="枚举值1"/>
<xs:enumeration value="枚举值2"/>
<xs:enumeration value="枚举值3"/>
......
</xs:restriction>
一个例子:
<xs:element name="sex">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="男"/>
<xs:enumeration value="女"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
还可以这样写:
<xs:element name="sex" type="sexType"/>
<xs:simpleType name="sexType">
<xs:restriction base="xs:string">
<xs:enumeration value="男"/>
<xs:enumeration value="女"/>
</xs:restriction>
</xs:simpleType>
第二种写法中sexType不属于sex独有,其他元素也能应用,第一种写法的simpleType对于外部是不可见的。
元素值的正则限定:
<xs:element name="userName">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z0-9-_]"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
对空白字符的限定:
<xs:whiteSpace value=""/>
这里的value有3种情况:
preserve: XML 处理器不会移除任何空白字符
replace: XML 处理器将移除所有空白字符(换行、回车、空格以及制表符)
collapse: XML 处理器将移除所有空白字符,开头和结尾的空格会被移除,而多个连续的空格会被缩减为一个单一的空格)
对字符长度的限定:
<xs:length value="8"/> 字符长度只能为8
<xs:minLength value="5"/> 字符最少5位
<xs:maxLength value="8"/> 字符最多8位
<xs:minExclusive value="0"/> 数字最小要大于0
<xs:maxExclusive value="100"/> 数字最大要小于100
<xs:minInclusive value="0"/> 数字最小要大于等于0
<xs:maxInclusive value="100"/> 数字最大要小于等于100 与上面的区别是 可以取临界值
<xs:fractionDigits value="3"/> 定义最大允许的小数位数,必须大于等于0
<xs:totalDigits value="6"/> 定义数字的精确位数,必须大于等于0,示例表示数字最大精确到6位
复合元素:
复合元素有以下几种类型:
1. 包含属性的空元素,如:<product id="1"/>
2. 包含子元素的元素,如:<student><name>zhangsan</name><sex>male</sex></student>
3. 仅包含文本的元素,如:<color>red</color>
4. 包含文本.属性.子元素任意组合的元素,如<product id="1"><name>T恤</name></product>
复合类型声明:
包含子元素情况
<xs:complexType name="复合元素名称">
<xs:sequence>
<xs:element name="" type=""/>
<xs:element name="" type=""/>
......
</xs:sequence>
</xs:complexType>
包含属性的空元素情况:
<xs:complexType name="复合类型名称">
<xs:attribute name="属性名称" type="属性数据类型"/>
</xs:complexType>
或:
<xs:complexType name="复合类型名称">
<xs:complexContent>
<xs:restriction base="xs:integer">
<xs:attribute name="属性名称" type="属性数据类型"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
仅包含文本的情况:
<xs:complexType name="复合类型名称">
<xs:simpleContent>
<xs:extension base="basetype">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
或:
<xs:complexType name="复合类型名称">
<xs:simpleContent>
<xs:restriction base="basetype">
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
包含属性和文本的情况:
<xs:complexType>
<xs:simpleContent>
<xs:extension base="基本数据类型">
<xs:attribute name="属性名称" type="属性数据类型"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
包含文本和子元素情况:需添加mixed="true",如:
<xs:complexType name="复合元素名称" mixed="true">
<xs:sequence>
<xs:element name="" type=""/>
<xs:element name="" type=""/>
......
</xs:sequence>
</xs:complexType>
复合类型继承:
<xs:complexType name="复合类型名称">
<xs:complexContent>
<xs:extension base="要继承的父元素名称">
<xs:sequence>
<xs:element name="" type=""/>
<xs:element name="" type=""/>
<xs:element name="" type=""/>
......这里element的定义顺序决定了在xml中出现的次序
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
XSD复合类型指示器:
首先分3大类:order指示器,Occurrence 指示器,Group 指示器
1. order指示器:
用于定义元素出现的次序
all 指示器:指示元素可以按任意次序出现,且最多只能出现1次
<xs:all>
<xs:element/>
<xs:element/>
...
</xs:all>
Choice 指示器:规定两个元素2选1显示,非此即彼
<xs:choice>
<xs:element/>
<xs:element/>
这里element只能是2个
</xs:choice>
Sequence 指示器:规定元素必须按定义的顺序出现
<xs:sequence>
<xs:element name="" type=""/>
<xs:element name="" type=""/>
<xs:element name="" type=""/>
......这里element的定义顺序决定了在xml中出现的次序
</xs:sequence>
2. Ocurrence指示器:
用于定义某个元素出现的频率(即元素能出现几次)
maxOccurs 指示器:元素能出现的最大次数
如:<xs:element name="元素名称" type="元素数据类型" maxOccurs="10"/>
maxOccurs="unbounded"表示元素出现次数不受任何限制
minOccurs 指示器:元素能出现的最小次数
如:<xs:element name="元素名称" type="元素数据类型" minOccurs="1"/>
3. Group 指示器
用于定义相关元素或属性的组包装
元素组Group指示器:对相关元素的进行归纳为组
如:
<xs:group name="元素组名称">
<xs:sequence>
<xs:element/>
<xs:element/>
......
</xs:sequnce>
</xs:group>
复合类型定义中引用这个group指示器:
<xs:complexType name="复合类型名称">
<xs:sequence>
<xs:group ref="元素组名称"/>
<xs:element name="元素名称" type="元素数据类型"/>
</xs:sequence>
</xs:complexType>
属性组attributeGroup指示器:用于对属性的组包装
如:
<xs:attributeGroup name="属性组名称">
<xs:attribute name="属性名称" type="属性数据类型"/>
<xs:attribute name="属性名称" type="属性数据类型"/>
<xs:attribute name="属性名称" type="属性数据类型"/>
......
</xs:attributeGroup>
元素中应用属性组:
<xs:element name="元素名称">
<xs:complexType>
<xs:attributeGroup ref="应用的属性组名称"/>
</xs:complexType>
</xs:element>
<!-- 指示器end-->
<xs:any minOccurs="0"/> 表示任意元素且可以出现任意次数
<xs:anyAttribute/> 表示可以是任意属性
元素替换:
<xs:element name="aaa" type="xs:string"/>
<xs:element name="navn" substitutionGroup="aaa"/>
上面示例表示可以用navn去代替aaa元素
阻止元素替换:
<xs:element name="aaa" type="xs:string" block="substitution"/>
上面示例表示禁止aaa元素被替换
下面分别是JDK使用DTD或XSD验证XML文件的代码:
package test;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
public class XMLValidate {
/**
* XSD验证XML(不依赖任何其他第三方Jar)
* @author Lanxiaowei
* @param xmlPath XML文件路径(相对CLASSPATH)
* @param xsdPath XSD文件路径(相对CLASSPATH)
* @return true/false 验证是否成功
*/
public boolean validateByXSD(String xmlPath, String xsdPath) {
try {
// 建立schema工厂
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// 利用schema工厂,接收验证文档文件对象生成Schema对象
Source schemaSource = new StreamSource(XMLValidate.class.getResourceAsStream(xsdPath));
//如果有多个xsd文件,可以这样构造Schema:schemaFactory.newSchema(Source[] sources);
Schema schema = schemaFactory.newSchema(schemaSource);
// 通过Schema产生针对于此Schema的验证器
Validator validator = schema.newValidator();
// 得到验证的数据源,即待验证的xml文件Source对象
Source source = new StreamSource(XMLValidate.class.getResourceAsStream(xmlPath));
validator.validate(source);
return true;
} catch (Exception e) {
return false;
}
}
/**
* DTD验证XML(不依赖任何其他第三方Jar)
*
* @param xmlPath XML文件路径(相对CLASSPATH)
* @param dtdPath DTD文件路径(相对CLASSPATH)
* @return true/false 验证是否成功
*/
public boolean validateByDTD(String xmlPath,final String dtdPath){
DocumentBuilderFactory factory;
DocumentBuilder builder;
try {
factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
builder = factory.newDocumentBuilder();
builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId)throws SAXException, IOException {
return new InputSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(dtdPath));
}
});
builder.setErrorHandler(new DTDErrorHandler());
Document xmlDocument = builder.parse(XMLValidate.class.getResourceAsStream(xmlPath));
//xml文档格式化
xmlDocument.getDocumentElement().normalize();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
/*try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
SAXParser jaxpParser = factory.newSAXParser();
XMLReader reader = jaxpParser.getXMLReader();
reader.parse(xmlPath);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}*/
}
//内部异常处理类
private class DTDErrorHandler implements ErrorHandler {
public void error(SAXParseException arg0) throws SAXException {
throw new SAXException(arg0.getSystemId() + " parse error at "
+ "line " + arg0.getLineNumber() + ",column "
+ arg0.getColumnNumber() + "," + arg0.getMessage());
}
public void fatalError(SAXParseException arg0) throws SAXException {
throw new SAXException("line " + arg0.getLineNumber() + ",column "
+ arg0.getColumnNumber() + "," + arg0.getMessage());
}
public void warning(SAXParseException arg0) throws SAXException {
throw new SAXException("line " + arg0.getLineNumber() + ",column "
+ arg0.getColumnNumber() + "," + arg0.getMessage());
}
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
//测试XSD验证XML
/*XMLValidate validate = new XMLValidate();
boolean result = validate.validateByXSD("/config/Noname1.xml", "/config/shiporder-2.xsd");
System.out.println(result);*/
//测试DTD验证XML
XMLValidate validate = new XMLValidate();
boolean result = validate.validateByDTD("/config/student.xml", "./config/student.dtd");
System.out.println(result);
}
}
package test;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class DTDErrorHandler implements ErrorHandler {
public void error(SAXParseException arg0) throws SAXException {
throw new SAXException(arg0.getSystemId() + " parse error at "
+ "line " + arg0.getLineNumber() + ",column "
+ arg0.getColumnNumber() + "," + arg0.getMessage());
}
public void fatalError(SAXParseException arg0) throws SAXException {
throw new SAXException("line " + arg0.getLineNumber() + ",column "
+ arg0.getColumnNumber() + "," + arg0.getMessage());
}
public void warning(SAXParseException arg0) throws SAXException {
throw new SAXException("line " + arg0.getLineNumber() + ",column "
+ arg0.getColumnNumber() + "," + arg0.getMessage());
}
}
最后简单说说什么是DTD,什么是Schema?DTD即Documnet Type Definition翻译过来就是文档类型定义,说的通俗一点就是DTD里描述了XML里可以自定义哪些元素,元素下可以出现哪些子元素以及子元素出现的频率,元素内容是需不需要XML解析器解析,即DTD的两种常用数据类型:PCDATA、CDATA,DTD就好比是XML的结构定义说明书,而XML就好比是数据介质,虽然XML的节点也有层次关系,但是表现出来的关系其实还是DTD里定义好的。至于Schema,它是DTD的升级版或者是增强版,由于DTD只能表示PCDATA、CDATA两种数据,没有类似其他语言的数据类型概念,所以Schema引入了数据类型,再个DTD没有命名空间的概念,如果两份XML的元素名称相同就无法区别开来,Schema于是引入了命名空间的概念。当然他们之间的不同还有很多,整体上讲就这两点不同。OK,就这些了。
忘了 没贴我测试用的DTD、XSD、XML文件的代码,sorry,现补上:
Noname1.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<my:shiporder my:orderid="889923" xmlns:xsi="" xmlns:my="">
<my:orderperson>Geroge Bush</my:orderperson>
<my:shipto>
<my:name>John Adams</my:name>
<my:address>0xford Street</my:address>
<my:city>London</my:city>
<my:country>UK</my:country>
</my:shipto>
<my:item>
<my:title>Empire Burlesque</my:title>
<my:note>Special Edition</my:note>
<my:quantity>1</my:quantity>
<my:price>10.90</my:price>
</my:item>
<my:item>
<my:title>Hide your heart</my:title>
<my:quantity>1</my:quantity>
<my:price>9.90</my:price>
</my:item>
</my:shiporder>
shiporder-2.xsd文件:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified">
<!-- 自定义类型-->
<xs:simpleType name="stringtype">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="inttype">
<xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>
<xs:simpleType name="decimaltype">
<xs:restriction base="xs:decimal"/>
</xs:simpleType>
<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>
<!-- 简易元素定义-->
<xs:element name="orderperson" type="stringtype"/>
<xs:element name="name" type="stringtype"/>
<xs:element name="address" type="stringtype"/>
<xs:element name="city" type="stringtype"/>
<xs:element name="country" type="stringtype"/>
<xs:element name="title" type="stringtype"/>
<xs:element name="note" type="stringtype"/>
<xs:element name="quantity" type="inttype"/>
<xs:element name="price" type="decimaltype"/>
<!-- 属性的定义 -->
<xs:attribute name="orderid" type="stringtype"/>
<!-- 复合类型定义-->
<xs:complexType name="shiptotype">
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="address"/>
<xs:element ref="city"/>
<xs:element ref="country"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="itemtype">
<xs:sequence>
<xs:element ref="title"/>
<xs:element ref="note" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="quantity"/>
<xs:element ref="price"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="shipordertype">
<xs:sequence>
<xs:element ref="orderperson"/>
<xs:element name="shipto" type="shiptotype"/>
<xs:element name="item" type="itemtype" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="orderid" use="required"/>
</xs:complexType>
<xs:element name="shiporder" type="shipordertype"></xs:element>
</xs:schema>
student.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student>
<id>1</id>
<name>张三1</name>
<sex>男</sex>
<birth>1979-09-26</birth>
<degree>高中</degree>
<hobby>音乐,Java</hobby>
<aa>aaa</aa>
</student>
<student>
<id>2</id>
<name>张三2</name>
<sex>男</sex>
<birth>1979-09-26</birth>
<degree>高中</degree>
<hobby>音乐,Java</hobby>
</student>
<student>
<id>3</id>
<name>张三3</name>
<sex>男</sex>
<birth>1979-09-26</birth>
<degree>高中</degree>
<hobby>音乐,Java</hobby>
</student>
<student>
<id>4</id>
<name>张三4</name>
<sex>男</sex>
<birth>1979-09-26</birth>
<degree>高中</degree>
<hobby>音乐,Java</hobby>
</student>
</students>
student.dtd文件:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT students (student+)>
<!ELEMENT student (id,name,sex,birth,degree,hobby)>
<!ELEMENT id (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ELEMENT birth (#PCDATA)>
<!ELEMENT degree (#PCDATA)>
<!ELEMENT hobby (#PCDATA)>
本文来源 我爱IT技术网 http://www.52ij.com/jishu/90.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
