DTD解、xml解析,xml建模简单理
一、DTD
1、什么是DTD
文档类型定义(Document Type Definition),是一种特殊文档,它规定、约束符合标准通用标示语言(SGML)或SGML子集可扩展标示语言(XML)规则的定义和陈述。
2、DTD的作用
通过DTD让我们在xml自定义标记,让解析器认识这些自定义的标记并更具这些自定义的标记的处理法则来处理元素。(简单的理解就是需要DTD文档才能使解析器对xml文件发挥作用)
3、DTD对于XML格式的要求(合法XML)
3.1:有且只有一个根节点
3.2:由开始标签和结束标签组成(包括开始标签和结束标签一体的标签)
3.3:xml标签区分大小写
3.4:xml中的标签要正确嵌套
4.使用DTD
(新建一个xml文件)
4.1:在xml中加入DTD申明
1)、内部申明:
2)、外部申明:
4.2:元素定义语法(DTD对元素的约束)
1)、基本语法: <! ELEMENT 元素名称 元素类型>
2)、元素分类:EMPTY 空元素 例:"<forward />"(前面的反斜杠是转义的)
(#PCDATA) 文本元素 例:<input>你好<input>
(e1,e2) 混合元素 例:<config >
<action><action>
<config >
3)、元素限制:,(顺序)、|(或,多选一)、?(0或1次),*(0次或多 次), +(1次或多次)
4.3 属性定义语法(DTD对属性的限制)
基本语法:<!ATTLIST 元素名称 属性名称 属性类型 设置说明>
属性类型:ID/CDATA/ENUM (男|女)
设置说明:#REQUIRED(必须)/#IMPLIED(可选)
4.4 特殊符号转义
&(逻辑与) --> &
>(大于) --> >
<(小于) --> <
‘(单引号) --> ’
“(双引号) --> "
5.正确演示代码:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action path CDATA #REQUIRED
type CDATA #REQUIRED>
<!ATTLIST forward name CDATA #REQUIRED
redirect (true|false) #REQUIRED
path CDATA #REQUIRED
>
]>
<!--
(所有标签要求):
config标签:可以包含0~N个action标签
action标签:可以饱含0~N个forward标签
path:以/开头的字符串,并且值必须唯一 非空
type:字符串,非空
forward标签:没有子标签;
name:字符串,同一action标签下的forward标签name值不能相同 ;
path:以/开头的字符串
redirect:只能是false|true, 允许空,默认值为false
-->
<action path="/regAction" type="test.RegAction">
<forward name="failed" path ="/reg.jsp" redirect="false" />
<forward name="success" path ="/login.jsp" redirect="true" />
</action>
<action path="/loginAction" type="test.LoginAction">
<forward name="failed" path="/login.jsp" redirect="false" />
<forward name="success" path="/main.jsp" redirect="true" />
</action>
二、xml解析
1、为什么要xml解析
为了方便不同数据语言之间的数据交换
2、解析所要做的准备
dom4j 和 xpath jar包(可以到官方网站上去下载)
3、xml中元素的组成 (由节点组成Node)
1)、元素节点
2)、属性节点
3)、文本节点
4、代码演示
public static void main(String[] args) throws DocumentException {
//用类名去与(Demo.class.).xml文件产生联系,将得到的Demo.xml中的内容放到is中
InputStream is = Demo.class.getResourceAsStream("/Demo.xml");
//new一个SAXReader,读取数据
SAXReader sa=new SAXReader();
//通过sa将得到的is放入到Document中
Document read = sa.read(is);
//得到Document中的所有的config节点
//多个查询 selectNodes("节点名");
List<Element> configList = read.selectNodes("/config");
//循环得到所有的config节点
for (Element e : configList) {
//得到每个config下的所有action节点
List<Element> actionList = e.selectNodes("action");
//循环每个action
for (Element action : actionList) {
String actionPath = action.attributeValue("path");
String actionType = action.attributeValue("type");
System.out.println("path:"+actionPath+" ,type:"+actionType);
//得到每一个forward
List<Element> forwardList = action.selectNodes("forward");
//循环得到每个forward
for (Element forward : forwardList) {
String forwardName = forward.attributeValue("name");
String forwardPath = forward.attributeValue("path");
String forwardRedirect = forward.attributeValue("redirect");
System.out.println("\t\tname:"+forwardName+" ,path:"+forwardPath+" ,redirect:"+forwardRedirect);
}
}
}
}
三、xml建模
1、为什么要xml建模
通过xml解析得到的数据,转化为java对象来供java语言来使用,实现不同语言之间的数据交流
2、如何建立实体类
根据xml中的每一个节点,只要是一个节点那就是一个实体类,从节点的最里层开始建立实体类,根据节点的个数写属性,每一个点都是一个属性,如果那个节点的同样的子节点为不确定的个数,那么这个属性就用map集合定义,再根据他的要求确定map集合的键位,一般是那个为 唯一值的属性为map集合的键位。
3、建模分析&代码
分析:根据上面的xml解析、及已知的xml可知,
config中的action节点的个数是不确定的,则action属性就用map集合
action中的forward节点的个数也是不确定的,则forward属性就是map集合,action的属性还包括他的type,path;
forward类的属性就为path、redirect,name
分析之后就可建立实体类,注意命名的规范
ForwardModel类package com.entity;
import java.util.HashMap;
import java.util.Map;
public class ActionModel {
private String path;
private String type;
private Map<String, ForwardModel> forwardModerls=new HashMap<>();
@Override
public String toString() {
return "ActionModel [path=" + path + ", type=" + type + ", forwardModerls=" + forwardModerls + "]";
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void push(ForwardModel forwardModel) {
forwardModerls.put(forwardModel.getName(), forwardModel);
}
public ForwardModel get(String name) {
return forwardModerls.get(name);
}
}
Action类
private String name;
private String path;
private boolean redirect;
public ForwardModel() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public boolean isRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
@Override
public String toString() {
return "ForwardModel [name=" + name + ", path=" + path + ", redirect=" + redirect + "]";
}
ConfigModel类
package com.entity;
import java.util.HashMap;
import java.util.Map;
public class ConfigModel {
private Map<String, ActionModel> actionModels=new HashMap<>();
@Override
public String toString() {
return "ConfigModel [actionModels=" + actionModels + "]";
}
public void push(ActionModel actionModel) {
actionModels.put(actionModel.getPath(), actionModel);
}
public ActionModel get(String path) {
return actionModels.get(path);
}
}
建立一个生产Config的类:ConfigModelFectory
package com.entity;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ConfigModelFectory {
private static final String DEFAULT_PATH="/Demo.xml";
//如果调用参数的时候没有传参数,则让它调用默认的路径
public static ConfigModel getConfigModel() {
return getConfigModel(DEFAULT_PATH);
}
//如果传了路径参数,则调用这个方法
public static ConfigModel getConfigModel(String xml_path) {
//实例化一个configModel
ConfigModel configModel=new ConfigModel();
//根据路径读取xml
InputStream is = ConfigModelFectory.class.getResourceAsStream(xml_path);
//定义一个读取出is中的对象
SAXReader read=new SAXReader();
try {
//读取到document中
Document doc = read.read(is);
//读取action节点
List<Element> actionList = doc.selectNodes("/config/action");
for (Element actionElement : actionList) {
//实例化一个action
ActionModel actionModel=new ActionModel();
//读取到action的path属性
String actionPath = actionElement.attributeValue("path");
//读取到action的type属性
String actionType = actionElement.attributeValue("type");
//读取到action的forward的节点
List<Element> forwardList = actionElement.selectNodes("forward");
for (Element forwardElement : forwardList) {
//实例化一个forward对象
ForwardModel forwardModel=new ForwardModel();
//得到forward的path属性
String forwardPath = forwardElement.attributeValue("path");
//得到forward的name属性
String forwardName = forwardElement.attributeValue("name");
//得到forward的redirect属性
String forwardRedirect = forwardElement.attributeValue("redirect");
//将值放到redirec对象中
forwardModel.setName(forwardName);
forwardModel.setPath(forwardPath);
forwardModel.setRedirect(Boolean.parseBoolean(forwardRedirect));
//将forwardModel对象放入到actionModel中
actionModel.push(forwardModel);
}
//将得到的值放入到actionModel对象中
actionModel.setPath(actionPath);
actionModel.setType(actionType);
configModel.push(actionModel);
}
} catch (DocumentException e) {
e.printStackTrace();
}
return configModel;
}
}
做测试:Demo
package com.text;
import com.entity.ConfigModel;
import com.entity.ConfigModelFectory;
public class Demo {
public static void main(String[] args) {
ConfigModel configModel = ConfigModelFectory.getConfigModel();
System.out.println(configModel.get("/loginAction"));
}
}
四、小结一下
无论是对于DTD文档,还是xml解析、及xml建模都是为了不同语言之间的数据的沟通在提供场所,每个内容都是数据交换的一个环节,这个是必不可少的,无论处于那个环节都有它存在的意义;xml解析及xml建模都不止上面那一种方法。