当前位置:网站首页>Xml的(DTD,xml解析,xml建模)
Xml的(DTD,xml解析,xml建模)
2022-07-03 10:44:00 【嘴强程序员】
目录
xml(Extensible Markup Language)可拓展标记语言
了解什么是良好的xml格式
xml(Extensible Markup Language)可拓展标记语言
1)XML的简单易于在任何应用程序中读/写数据,这使XML很快成为数据交换的唯一公共语言,虽然不同的应用软件也支持其他的数据交换格式,但不久之后它们都将支持XML,那就意味着程序可以更容易的与Windows、Mac OS、Linux以及其他平台下产生的信息结合,然后可以很容易加载XML数据到程序中并分析它,并以XML格式输出结果。
2)xml可用作数据的说明、储存、传输
举个例子:假设一个微信群里面小明发了一条消息“你吃过没”。而这条消息发出后会被储存到服务器里,而当你进入微信的时候,这条消息就会从服务器里抓取过来显示到你的手机上。而这个抓取的过程中假设是以xml文件来传输(也有json,json和xml用途很相似,json、xml都有自己的格式,但其实都只是包装数据时格式不同而已,重要的是其中含有的数据,而不是包装的格式。这里只是举个例子)这时,我们用通俗易懂的文字来表示就是:
发送者:小明
聊天组:xxxx
信息:你吃过没
很明显我们人可以体会字面意思,并自动拆分出数据的,但机器却看不行,所以在传入之前它是通过xml的格式来让机器能识别的出来:
<msg> <sender ="小明" /> <groupid = 112221 /> <type = test/> <content = "你吃过没" /> </msg>
格式大概是这样,具体的如果感兴趣可以自己去网上看看,这里只是举个例子。这样表示就很直观,附带了对数据的说明,并且具备通用的格式规范可以让程序做解析。
3)xml文件现在多用于作配置文件,设置文件比较多,很多软件,框架都会采取xml作为配置文件。像在Android Studio中创建一个项目时,开始会弹出一个Configure your project(配置你的项目),而你在上面输入的项目名,包名什么的都会帮你存储到AndroidManifest.xml 文件里,此xml文件里还会默认配置好项目的一些属性和一个MainActivty以及这个activty的一些属性,并且在之后一些组件(Activty,service等)都是要在这里面注册并配置的。
既然提到json,那么也来说一下。
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。
1)JSON基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
2)json和xml优缺点对比:
①可读性方面。
JSON和XML的数据可读性基本相同,JSON和XML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,XML可读性较好些。
②可扩展性方面。
XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
③编码难度方面。
XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有http://json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
④解码难度方面。
XML的解析得考虑子节点父节点,让人头昏眼花,而JSON的解析难度几乎为0。这一点XML输的真是没话说。
⑤流行度方面。
XML已经被业界广泛的使用,而JSON才刚刚开始,但是在Ajax这个特定的领域,未来的发展一定是XML让位于JSON。到时Ajax应该变成Ajaj(Asynchronous Javascript and JSON)了。
⑥解析手段方面。
JSON和XML同样拥有丰富的解析手段。
⑦数据体积方面。
JSON相对于XML来讲,数据的体积小,传递的速度更快些。
⑧数据交互方面。
JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。
⑨数据描述方面。
JSON对数据的描述性比XML较差。
⑩传输速度方面。
JSON的速度要远远快于XML。
总结
xml与json的使用都比较类似,但如今程序员更青睐json, 而且市面上有各种各样现成的json开发库可直接使用。所以现在大多使用json来做为数据传输,如很多webservice的api 返回的大多是json格式。而xml现在一般主要用作配置文件,设置文件比较多。
1.DTD元素定义
拥有正确语法的 XML 被称为"形式良好"的 XML。
通过 DTD 验证的XML是"合法"的 XML。
符号 | 用途 | 示例说明 |
() | 用来给元素分组 | 分成两组 |
| | 在列出的对象中选择一个 | 表示男人或者女人必须出现,两者至少选其一 |
+ | 该对象必须出现一次或者多次 | 表示成员必须出现,而却可以出现多个成员 |
* | 该对象允许出现0次或者多次 | 爱好可以出现两次到多次 |
? | 该对象必须出现0次或者1次 | 菜鸟可以出现,也可以不出现,如果出现的话,最多只能出现一次 |
, | 对象必须按指定的顺序出现 | 表示西瓜、苹果、香蕉必须出现,并且按这个顺序出现 |
属性定义的语法
<!ATTLIST element-name att_name type> (attlist可以存在多个属性,元素)(element-name放的是元素)(att_name放的是属性名称)(type属性类型)
ID (唯一的)
(男|女) “男” (枚举或默认)
CDATA (普通文本)
IDREF (类似数据库外键)
#REQUIRED/#IMPLIED(非空/可以空)
xml特殊符号
&(逻辑与) & ;
<(小于号) <;
.>(大于号) > ;
"(双引号) " ;
'(单引号) &qpos ;
SYSTEM (指的是引用当前项目的DTD)
PUBLIC (公开的,引用互联网上的DTD)
案例1
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE persons[
<!ELEMENT persons (person+)>
<!ELEMENT person (name,age,contact,br*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT contact (phone|email)>
<!ELEMENT br EMPTY>
<!ATTLIST person
pid ID #REQUIRED
sex (男|女) '男'
qq CDATA #IMPLIED
parent IDREF #IMPLIED
>
]>
<persons>
<person pid="p1" sex="男" qq="aaa" parent="p2">
<name>张小明</name>
<age>10</age>
<contact>
<phone>1234567</phone>
</contact>
<br/>
</person>
<person pid="p2">
<name>张大明</name>
<age>35</age>
<contact>
<email>[email protected]</email>
</contact>
</person>
</persons>
案例2
<?xml version="1.0" encoding="UTF-8"?>
<!--
config标签:可以包含0~N个action标签
-->
<--
声明 config是根节点 然后他里面最少要有一个action 或多个
-->
<!DOCTYPE config[
<!ELEMENT config (action+)>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action
path CDATA #REQUIRED
type CDATA #REQUIRED
>
<!ATTLIST forward
path CDATA #REQUIRED
name CDATA #IMPLIED
redirect (true|false) "false"
>
]>
<config>
<!--
action标签:可以饱含0~N个forward标签 path:以/开头的字符串,并且值必须唯一 非空 ,子控制器对应的路径
type:字符串,非空,子控制器的完整类名
-->
<action path="/registerAction" type="test.action.RegisterAction">
<forward name="success" path="/index.jsp" redirect="true" />
<forward name="failed" path="/register.jsp" redirect="false" />
</action>
<action path="/loginAction" type="test.action.LoginAction">
<forward name="a" path="/index.jsp" redirect="false" />
<forward name="b" path="/welcome.jsp" redirect="true" />
</action>
</config>
2.xml文件解析
所用jar包 dom4j
架包下载
xml解析架包 密码:hlx8
导入如上dom4j架包
1,生成xml文件
所生成的xml文件
生成xml文件代码演示package com.zking.listtext; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.junit.Test; import java.io.File; import java.io.FileOutputStream; public class TextXml { /** * 使用DOM4J生成xml方法 */ @Test public static void createXml(){ try { // 创建document对象 Document document = DocumentHelper.createDocument(); // 创建根节点bookRoot Element StudentRoot = document.addElement("StudentRoot"); // 向根节点中添加第一个节点 Element book1 = StudentRoot.addElement("student"); // 向子节点中添加属性 book1.addAttribute("id","1"); // 向节点中添加子节点 Element name = book1.addElement("name"); // 向子节点赋值 name.setText("小乔"); Element price = book1.addElement("age"); price.setText("18"); // 向根节点中添加第二个节点 Element book2 = StudentRoot.addElement("student"); book2.addAttribute("id","2").addElement("name").setText("大桥"); book2.addElement("age").setText("20"); // 向根节点中添加第三个节点 Element book3 = StudentRoot.addElement("student"); book3.addAttribute("id","3").addElement("name").setText("孙策"); book3.addElement("age").setText("21"); // 设置生成xml的格式 OutputFormat of = OutputFormat.createPrettyPrint(); // 设置编码格式 of.setEncoding("UTF-8"); // 生成xml文件 File file = new File("resources/Student.xml"); if (file.exists()){ file.delete(); } //创建一个xml文档编辑器 XMLWriter writer = new XMLWriter(new FileOutputStream(file), of); //把刚刚创建的document放到文档编辑器中 writer.write(document); writer.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { TextXml.createXml(); } }
2.解析xml文件
1.直接读取文件
public static void analysis(){ // 把要解析的xml变成file文件 File file = new File("resources/Student.xml"); // 获取解析器对象 SAXReader reader = new SAXReader(); // 把文件解析成document树 Document document = null; try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); } // 获取根节点 Element studentRoot = document.getRootElement(); // 获取根节点中所有节点 List<Element> elements = studentRoot.elements(); // 便利所有节点 for (Element child : elements) { System.out.println("----------------"); //已知属性名情况下 System.out.println(Integer.parseInt(child.attributeValue("id")));//获取属性的数据 //已知子元素名的情况下 System.out.println(child.elementText("name"));//获取元素中值 System.out.println(Integer.parseInt(child.elementText("age")));//获取元素中值 //未知属性名情况下 使用 List<Attribute> attributes = child.attributes(); for (Attribute attribute : attributes) { System.out.println(attribute.getName() + "---> " + attribute.getValue()); } //未知子元素名情况下 子节点 List<Element> elementList = child.elements(); for (Element ele : elementList) { System.out.println(ele.getName() + "--->" + ele.getText()); } } //把解析xml出来的数据集合打印 // list.forEach(x-> System.out.println(x)); }
2.通过类的加载器 文件在项目中时
public static void xmlClass(){ // 获取类的Class对象 在获取文件流对象 Class<TextXml> ac = TextXml.class; // 加载器中的/代表本工作目录下找 src中 InputStream in = ac.getResourceAsStream("/Student.xml"); // 获取解析器对象 SAXReader reader = new SAXReader(); // 把文件解析成document树 Document document = null; try { document = reader.read(in); } catch (DocumentException e) { e.printStackTrace(); } // 获取根节点 Element studentRoot = document.getRootElement(); // 获取根节点中所有节点 List<Element> elements = studentRoot.elements(); // 便利所有节点 for (Element child : elements) { System.out.println("----------------"); //已知属性名情况下 System.out.println(Integer.parseInt(child.attributeValue("id")));//获取属性的数据 //已知子元素名的情况下 System.out.println(child.elementText("name"));//获取元素中值 System.out.println(Integer.parseInt(child.elementText("age")));//获取元素中值 //未知属性名情况下 使用 List<Attribute> attributes = child.attributes(); for (Attribute attribute : attributes) { System.out.println(attribute.getName() + "---> " + attribute.getValue()); } //未知子元素名情况下 子节点 List<Element> elementList = child.elements(); for (Element ele : elementList) { System.out.println(ele.getName() + "--->" + ele.getText()); } } //把解析xml出来的数据集合打印 // list.forEach(x-> System.out.println(x)); }
3.xml建模
什么是建模,为什么要建模
1.什么是建模
建模就是针对xml配置文件键类的过程就是建模。
2.为什么要建模
为了方便在内存当中使用xml配置文件所以需要建模。
建模所用到的xml文件
<?xml version="1.0" encoding="UTF-8"?> <!-- config标签:可以包含0~N个action标签 --> <!DOCTYPE config[ <!ELEMENT config (action+)> <!ELEMENT action (forward*)> <!ELEMENT forward EMPTY> <!ATTLIST action path CDATA #REQUIRED type CDATA #REQUIRED > <!ATTLIST forward path CDATA #REQUIRED name CDATA #IMPLIED redirect (true|false) "false" > ]> <config> <!-- action标签:可以饱含0~N个forward标签 path:以/开头的字符串,并且值必须唯一 非空 ,子控制器对应的路径 type:字符串,非空,子控制器的完整类名 --> <action path="/registerAction" type="test.action.RegisterAction"> <forward name="success" path="/index.jsp" redirect="true" /> <forward name="failed" path="/register.jsp" redirect="false" /> </action> <action path="/loginAction" type="test.action.LoginAction"> <forward name="a" path="/index.jsp" redirect="false" /> <forward name="b" path="/welcome.jsp" redirect="true" /> </action> </config>
开始建模 建模从里到外建模
那么先从最底层的<forward>元素开始,我们先仔细观察会发现<forward>元素中有三个属性分别是name,path,pedirect三个这里值得一提的是name属性是不能重复的,path属性是必须以“/”好开头了解完这些以后我们便可以开始着手写代码的首先把对应的属性在java类中创建好,然后写好get和set方法如下图所示
因为path属性有限制必须以“/”号开头所以这里使用了正则表达式,在set方法中给path赋值之前进行判断如下图,这样我们的第一个元素类就写完了
set方法中用正则表达式进行判断
forward元素实体建模
package com.zking.resourt; import java.lang.reflect.Field; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ForwardModel { private String name; private String path; private boolean redirect=false; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPath() { return path; } public void setPath(String path) { //通过反射 因为定义的正则时私有的 调用action模型中写好的正则 Class<ActionModel> actionModelClass = ActionModel.class; try { Field pattern = actionModelClass.getDeclaredField("pattern"); pattern.setAccessible(true); Object o = pattern.get(actionModelClass); Matcher matcher = Pattern.compile(o.toString()).matcher(path); boolean matches = matcher.matches(); if(!matches){ throw new RuntimeException("forward的path必须以”/“开头 并且不能重复"); } this.path = path; } catch (Exception e) { throw new RuntimeException(e); } } public boolean isRedirect() { return redirect; } public void setRedirect(String redirect) { // System.out.println("方法中打印="+redirect.equals("true")); if(redirect.equals("true")){ this.redirect = true; }else{ this.redirect = false; } //或者 // this.redirect=Boolean.parseBoolean(redirect); } @Override public String toString() { return "ForwardModel{" + "name='" + name + '\'' + ", path='" + path + '\'' + ", redirect=" + redirect + '}'; } public ForwardModel(){ super(); } public static void main(String[] args) { new ForwardModel().setPath("1"); } }
action元素实体建模
package com.zking.resourt; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ActionModel { private String path; private String type; private Map<String,ForwardModel> forw; //path必须一斜杠开头不能重复 private static Pattern pattern=Pattern.compile("^/.+$"); public ForwardModel getForw(String key) { return forw.get(key); } public void setForw(ForwardModel fw) { if(forw==null){ forw=new HashMap<>(); } this.forw.put(fw.getName(), fw); } public String getPath() { return path; } public void setPath(String path) { //用定义号的正则 Matcher matcher = pattern.matcher(path); boolean matches = matcher.matches(); if(!matches){ throw new RuntimeException("action的path必须以”/“开头 并且不能重复"); } this.path = path; } public String getType() { return type; } public void setType(String type) { this.type = type; } public ActionModel() { } @Override public String toString() { return "ActionModel{" + "path='" + path + '\'' + ", type='" + type + '\'' + ", forw=" + forw + '}'; } }
根节点config建模
package com.zking.resourt; import java.util.HashMap; import java.util.Map; /** * 根节点模型 */ public class ConfigModel { private Map<String,ActionModel> word; //根据设置的剑获取模型中解析的xml类容 public ActionModel getWord(String path) { return word.get(path); } public void setWord(ActionModel word) { if(this.word==null){ this.word=new HashMap<>(); } this.word.put(word.getPath(), word); } }
解析并生成模型,测试
package com.zking.resourt; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import java.io.InputStream; import java.util.List; public class PropectiesRead { public static void main(String[] args) throws Exception { InputStream in = PropectiesRead.class.getResourceAsStream("/config.xml"); SAXReader reaber = new SAXReader(); //把配置文件读取到内存 Document read = reaber.read(in); //获取根元素 Element root = read.getRootElement(); //获取节点中confing下的action //Node node=read.selectSingleNode("/config"); List<Element> list = root.selectNodes("/config/action"); //实例化根节点模型 ConfigModel con = new ConfigModel(); for (Element action : list) { String path = action.attributeValue("path"); String type = action.attributeValue("type"); //实例化子节点模型action ActionModel ac = new ActionModel(); //属性加入模型中 ac.setPath(path); ac.setType(type); //实例化子节点forward ForwardModel fo = new ForwardModel(); //获取action下所有的forward List<Element> forward = action.selectNodes("forward"); for (Element ward : forward ) { String fpath = ward.attributeValue("path"); String name = ward.attributeValue("name"); String s = ward.attributeValue("redirect"); /** * 将获取的属性加入模型中 */ fo.setPath(fpath); fo.setName(name); fo.setRedirect(s); ac.setForw(fo); boolean b = Boolean.parseBoolean(s); System.out.println(b); con.setWord(ac); } System.out.println("-------------------------------"); } // action中的属性 registerAction 需要获取的属性 ActionModel word = con.getWord("/registerAction"); System.out.println(word); //获取forward中 属性下的failed System.out.println(word.getForw("failed")); } }
最后测试结果
边栏推荐
- How to become a senior digital IC Design Engineer (1-5) Verilog coding syntax: operand
- Numpy np.max和np.maximum实现relu函数
- R语言使用data.table包进行数据聚合统计计算滑动窗口统计值(Window Statistics)、计算滑动分组中位数(median)并合并生成的统计数据到原数据集中
- 软考中级软件设计师该怎么备考
- DS90UB949
- How to become a senior digital IC Design Engineer (1-2) Verilog coding syntax: Verilog 1995, 2001, 2005 standards
- R语言使用aggregate函数计算dataframe数据分组聚合的均值(sum)、不设置na.rm计算的结果、如果分组中包含缺失值NA则计算结果也为NA
- 【obs】封装obs实现采集的基础流程
- Use typora to draw flow chart, sequence diagram, sequence diagram, Gantt chart, etc. for detailed explanation
- The world's most popular font editor FontCreator tool
猜你喜欢
GCC compilation process and dynamic link library and static link library
Matlab extracts numerical data from irregular txt files (simple and practical)
鸿蒙第四次培训
Summary of interview questions (2) IO model, set, NiO principle, cache penetration, breakdown avalanche
How to get started embedded future development direction of embedded
LeetCode 46:全排列
Balance between picture performance of unity mobile game performance optimization spectrum and GPU pressure
Excel快速跨表复制粘贴
uniapp scroll view 解决高度自适应、弹框滚动穿透等问题。
用了这么久线程池,你真的知道如何合理配置线程数吗?
随机推荐
Struct function & function pointer
Stm32hal library upgrades firmware based on flash analog U disk (detailed explanation)
Qt+VTK+OCCT读取IGES/STEP模型
Bi skills - permission axis
2022 东北四省赛 VP记录/补题
After a month, I finally got Kingdee offer! Share tetrahedral Sutra + review materials
R语言ggplot2可视化:gganimate包创建动态折线图动画(gif)、使用transition_reveal函数在动画中沿给定维度逐步显示数据、在折线移动方向添加数据点
MATLAB extrait les données numériques d'un fichier txt irrégulier (simple et pratique)
Mmc5603nj geomagnetic sensor (Compass example)
Cadence background color setting
Analysis of JMM memory model
Some common terms
How to mix embedded MCU, arm and DSP?
Processes and threads
Phpcms prompt message page Jump showmessage
抓包整理外篇fiddler———— 会话栏与过滤器[二]
Android log system
软件测试周刊(第78期):你对未来越有信心,你对现在越有耐心。
Double linked list of linear list
FL Studio 20无限试用版水果编曲下载