dtd/xsd 这点事

dtd/xsd 这点事

工作多年,发现以前不怎么在乎的东西,越发是大有文章。值得我们去深入学习下。最近公司的时间比较宽松,想把以前只会用的东西,继续学习下。才发现不懂的东西还是比较多的。本着“知其然,知其所以然”的态度,这里记录下一些文字。

今天在看hibernate源码的时候,发现hibernate包下有个hibernate-configuration-3.0.dtd文件,而spring关于配置方面的验证文件却是spring-beans-3.0.xsd文件。那么dtd文件跟xsd文件之间有什么不同呢?下面介绍一下DTD,XSD的区别。

1.DTD(Documnet Type Definition)
DTD即文档类型定义,是一种XML约束模式语言,是XML文件的验证机制,属于XML文件组成的一部分。
DTD 是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。 

一个 DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则。
2.XSD(XML Schemas Definition) 
XSD:XML结构定义,XML Schema描述了XML文档的结构。
可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其要求。XML Schema本身是一个XML文档,它符合XML语法结构。可以用通用的XML解析器解析它。
一个XML Schema会定义:文档中出现的元素、文档中出现的属性、子元素、子元素的数量、子元素的顺序、元素是否为空、元素和属性的数据类型、元素或属性的默认 和固定值。

对比下

DTD文件

XSD文件

支持对XML文件的验证?

支持

支持

是XML语法编码?

不是

是的,可以像其他XML文件一样解析和处理

可扩展吗?

不可

可以

支持命名空间吗?

不可

可以

可扩充数据类型?

只提供非常有限的数据类型 

可以

可见XSD要比DTD文件丰富。

实例说明:

一个XML文档:

<?xml version="1.0"?>
<!-- 本文档根元素为gridbag, 其中验证文档为gridbag.dtd -->
<!DOCTYPE gridbag SYSTEM "gridbag.dtd">
<gridbag>
	<row>
		<cell anchor="EAST">
			<bean>
				<class>javax.swing.JLabel</class>
				<property>
					<name>text</name>
					<value>
						<string>Face:</string>
					</value>
				</property>
			</bean>
		</cell>
		<cell fill="HORIZONTAL" weightx="100">
			<bean id="face">
				<class>javax.swing.JComboBox</class>
			</bean>
		</cell>
		<cell gridheight="4" fill="BOTH" weightx="100" weighty="100">
			<bean id="sample">
				<class>javax.swing.JTextArea</class>
				<property>
					<name>text</name>
					<value>
						<string>The quick brown fox jumps over the lazy dog</string>
					</value>
				</property>
				<property>
					<name>editable</name>
					<value>
						<bolean>false</bolean>
					</value>
				</property>
				<property>
					<name>lineWrap</name>
					<value>
						<boolean>true</boolean>
					</value>
				</property>
				<property>
					<name>border</name>
					<value>
						<bean>
							<class>javax.swing.border.EtchedBorder</class>
						</bean>
					</value>
				</property>
			</bean>
		</cell>
	</row>
	<row>
		<cell gridwidth="2" weighty="100">
			<bean id="bold">
				<class>javax.swing.JCheckBox</class>
				<property>
					<name>text</name>
					<value>
						<string>Bold</string>
					</value>
				</property>
			</bean>
		</cell>
	</row>
	<row>
		<cell gridwidth="2" weighty="100">
			<bean id="italic">
				<class>javax.swing.JCheckBox</class>
				<property>
					<name>text</name>
					<value>
						<string>Italic</string>
					</value>
				</property>
			</bean>
		</cell>
	</row>
</gridbag>

 DTD文件描述

<!ELEMENT gridbag (row)*>  <!--根元素是gridbag,可以多个子元素row-->
<!ELEMENT row (cell)*>  <!--row下面可以有多个cell子元素 -->
<!ELEMENT cell (bean)> <!--cell元素下只有一个bean元素-->
<!ATTLIST cell gridx CDATA #IMPLIED>  <!--cell有gridx属性,类型为任意文本,如果有特殊字符用相应的替代字符代替(用于属性中),可选-->
<!ATTLIST cell gridy CDATA #IMPLIED> 
<!ATTLIST cell gridwidth CDATA "1"> <!--gridwidhth属性默认为1-->
<!ATTLIST cell gridheight CDATA "1">
<!ATTLIST cell weightx CDATA "0">
<!ATTLIST cell weighty CDATA "0">
<!ATTLIST cell fill (NODE|BOTH|HORIZONTAL|VERTICAL) "NONE"> <!--fill属性有几个可选值,默认为NONE-->
<!ATTLIST cell anchor (CENTER|NORTH|NORTHEAST|EAST|SOUTHEAST|SOUTH|SOUTHWEST|WEST|NORTHWEST) "CENTER">
<!ATTLIST cell ipdx CDATA "0">
<!ATTLIST cell ipady CDATA "0">

<!ELEMENT bean (class, property*)> <!--bean子元素有一个class子元素,多个property子元素-->
<!ATTLIST bean id ID #IMPLIED> <!--bean的id属性是ID类型,也就是唯一性 -->

<!ELEMENT class (#PCDATA)> <!--class元素下面可以只包含文本也可以包含子元素,类似于ANY(用于元素中)-->
<!ELEMENT property (name, value)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT value (int|string|boolean|bean)>
<!ELEMENT int (#PCDATA)>
<!ELEMENT string (#PCDATA)>
<!ELEMENT boolean (#PCDATA)>

XSD文件描述: 

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mysite.org/schema/mytag"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
	targetNamespace="http://www.mysite.org/schema/mytag"
	elementFormDefault="qualified" attributeFormDefault="unqualified">
	<xsd:element name="gridbag" type="GridBagType" /><!--根元素 -->
	<xsd:element name="bean" type="BeanType" />
	<xsd:complexType name="GridBagType">
		<xsd:sequence>
			<xsd:element name="row" type="RowType" minOccurs="0"
				maxOccurs="unbounded" />
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="RowType">
		<xsd:sequence>
			<xsd:element name="cell" type="CellType" minOccurs="0"
				maxOccurs="unbounded" />
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="CellType">
		<xsd:sequence>
			<xsd:element ref="bean"></xsd:element>
		</xsd:sequence>
		<xsd:attribute name="gridx" type="xsd:int" use="optional" />
		<xsd:attribute name="gridy" type="xsd:int" use="optional"></xsd:attribute>
		<xsd:attribute name="gridwidth" type="xsd:int" use="optional"
			default="1"></xsd:attribute>
		<xsd:attribute name="gridheight" type="xsd:int" use="optional"
			default="1" />
		<xsd:attribute name="weightx" type="xsd:int" use="optional"
			default="0" />
		<xsd:attribute name="weighty" type="xsd:int" use="optional"
			default="0" />
		<xsd:attribute name="fill" use="optional" default="NONE">
			<xsd:simpleType>
				<xsd:restriction base="xsd:string">
					<xsd:enumeration value="NONE" />
					<xsd:enumeration value="BOTH" />
					<xsd:enumeration value="HORIZONTAL" />
					<xsd:enumeration value="VERTICAL"></xsd:enumeration>
				</xsd:restriction>
			</xsd:simpleType>
		</xsd:attribute>
		<xsd:attribute name="anchor" use="optional" default="CENTER">
			<xsd:simpleType>
				<xsd:restriction base="xsd:string">
					<xsd:enumeration value="CENTER"></xsd:enumeration>
					<xsd:enumeration value="NORTH" />
				</xsd:restriction>
			</xsd:simpleType>
		</xsd:attribute>
		<xsd:attribute name="ipady" type="xsd:int" use="optional"
			default="0"></xsd:attribute>
		<xsd:attribute name="ipadx" type="xsd:int" use="optional"
			default="0" />
	</xsd:complexType>
	<xsd:complexType name="BeanType">
		<xsd:sequence>
			<xsd:element name="class" type="xsd:string" />
			<xsd:element name="property" type="PropertyType"
				minOccurs="0" maxOccurs="unbounded" />
		</xsd:sequence>
		<xsd:attribute name="id" type="xsd:ID" use="optional"></xsd:attribute>
	</xsd:complexType>
	<xsd:complexType name="PropertyType">
		<xsd:sequence>
			<xsd:element name="name" type="xsd:string" />
			<xsd:element name="value" type="ValueType" />
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="ValueType">
		<xsd:choice>
			<xsd:element ref="bean" />
			<xsd:element name="int" type="xsd:int" />
			<xsd:element name="string" type="xsd:string" />
			<xsd:element name="boolean" type="xsd:boolean" />
		</xsd:choice>
	</xsd:complexType>
</xsd:schema>

Spring中 XSD文件对XML校验:

   见博客另一I篇文章。

Herbernate 中DTD 文件对XML校验:

      正常的 dom4j 读取 xml 的方式如下:

 

package com.zs.test.xsd;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class DTDExample
{
    public static String fileRealPath = "D:/vingsoft2/clientTest/src/com/zs/test/xsd/";
    
    public static void main(String[] args)
        throws DocumentException, IOException
    {
        
        EntityResolver resolver = new EntityResolver()
        {
            public InputSource resolveEntity(String publicId, String systemId)
                throws SAXException, IOException
            {
                // 这个publicId 没有搞明白? 
                   System.out.println(publicId);
                // file:///D:/vingsoft2/clientTest/src/com/zs/test/xsd/gridbag.dtd
                System.out.println(systemId);
                if (systemId.endsWith("gridbag.dtd"))
                {
                    InputStream in = new FileInputStream(new File(fileRealPath + "gridbag.dtd"));
                    return new InputSource(in);
                }
                return null;
            }
        };
        SAXReader reader = new SAXReader();
        reader.setEntityResolver(resolver); // 负责绑定dtd文件,对xml文件进行校验
         reader.setValidation(true);// 是否需要验证
         Document doc = reader.read(new File(fileRealPath + "MyXml.xml"));
        Element root = doc.getRootElement();
        
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding(doc.getXMLEncoding());
        XMLWriter writer = new XMLWriter(new FileOutputStream(fileRealPath + "haha.xml"), format);
        writer.write(doc);
        writer.close();
    }
}

  Hibernate在读取配置文件,进行XML校验的时候,主要用到了三个类:

 org.hibernate.cfg.Configuration

 org.hibernate.util.XMLHelper

 org.hibernate.util.DTDEntityResolver

URL定义 写道
private static final String URL = "http://hibernate.sourceforge.net/"

hibernate对校验文件的绑定 写道

public InputSource resolveEntity (String publicId, String systemId) {
		if ( systemId!=null && systemId.startsWith(URL) ) {			
			log.debug("trying to locate " + systemId + " in classpath under org/hibernate/");
			// Search for DTD
			String path = "org/hibernate/" + systemId.substring( URL.length() );
			InputStream dtdStream = resourceLoader==null ? 
					getClass().getResourceAsStream(path) :
					resourceLoader.getResourceAsStream(path);
			if (dtdStream==null) {
				log.debug(systemId + " not found in classpath");
				if ( systemId.substring( URL.length()).indexOf("2.0")>-1 ) {
					log.error("Don't use old DTDs, read the Hibernate 3.x Migration Guide!");
				}
				return null;
			}
			else {
				log.debug("found " + systemId + " in classpath");
				InputSource source = new InputSource(dtdStream);
				source.setPublicId(publicId);
				source.setSystemId(systemId);
				return source;
			}
		}
		else {
			// use the default behaviour			
			return null;
		}
	}

参考:

http://lg-asus.iteye.com/blog/1517942

http://www.w3school.com.cn/dtd/

http://www.w3school.com.cn/schema/index.asp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值