学习XML对任何类型的应用开发都很有帮助 比如可以在应用中有些经常要改变的配置或者像网站的后台管理DIY部分都可能会用到一些配置的修改 XML这种数据表现形式 是非常好的解决办法 另外对于学习AJAX也有很大的好处 因为DOM是一个已经标准化了的解析办法 在javascript中也会同样要处理文档结构 只是语法不同 只用再掌握JavaScript的DOM API 就可以很轻松的达到同样的效果
产生: 为了解决更清晰的表达层次结构和重复元素 使读写变得更简单 代替properties的一种方案
tips :
1 XML是大小写敏感的
2 XML的结束标签不能省略
3 XML中 只有一个标签而没有相对应的结束标签的元素必须以 "/"结尾
4 属性值必须用引号括起来
5 所有属性值必须有属性
6 最好值包括文本或者只包括子元素 不要两者兼有 避免出现:
<t1>
text1
<t2>text2</t2>
</t1>
7 一个重要的规则: 属性只是用来修饰值
解析XML (以SUN的api为基础)
要构造一个DocumentBuilder对象 可以从DocumentBuilderFactory中得到
方法
DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
DocumentBuilderbuilder=factory.newDocumentBuilder();
然后就能获得一个Document对象
Document是XML的树型结构的具体形式的表现 由实现Node接口及多个子接口的对象构成
得到一个Document
Filef=newFile("bin/hibernate.cfg.xml");
Documentdoc=builder.parse(f);
一些其他的构造方法(DocumentBuilder)
API中看出可以用URL和IO中的类来构造Document
重要接口
Node 是整个对象模型的主要数据类型 表示该文档树的单个节点 实现Node的接口有 Document Text Element Entity 等
tip : 并不是所有的Node都有子节点 如text 不同的接口会有更加合理和简单的获取和设置的相关方法
Document是用来表示整个XML或者Html之类的文档 是文档的根 提供数据的访问和构造以及修改方法
另:document也是实现Node的接口
NodeList接口提供对节点的有序集合的抽象,没有定义或约束如何实现此集合。DOM 中的 NodeList
对象是活动的。
NodeList
中的项可以通过从 0 开始的整数索引进行访问。
Text 表示Element或者Attr的文本内容
Element
接口表示 HTML 或 XML 文档中的一个元素。元素可能有与它们相关的属性;由于 Element
接口继承自 Node
,所以可以使用一般 Node
接口属性 attributes
来获得元素所有属性的集合。Element
接口上有通过名称获得 Attr
对象或通过名称获得属性值的方法。在 XML 中(其中的属性值可能包含实体引用),应该获得 Attr
对象来检查表示属性值的可能相当复杂的子树。另一方面,在 HTML 中(其中的所有属性都有简单的字符串值),可以使用直接访问属性值的方法,这既安全又便捷。
NamedNodeMap 实现 NamedNodeMap
接口的对象用于表示可以通过名称访问的节点的集合。注意,NamedNodeMap
不从 NodeList
继承;不以任何特定的顺序维护 NamedNodeMaps
。在实现 NamedNodeMap
的对象中包含的对象还可以通过顺序索引进行访问,但只允许方便地枚举 NamedNodeMap
的内容,并不意味着 DOM 指定这些节点的顺序。
例子:
解析一个xml文档来 基本接口及其方法的应用
我就把我的hibernate.cfg.xml拿来玩 当然Hibernate本身是用Dom4J的
<?xmlversion='1.0'encoding='UTF-8'?>
<!DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/HibernateConfigurationDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!--GeneratedbyMyEclipseHibernateTools.-->
<hibernate-configuration>
<session-factory>
<propertyname="connection.driver_class">com.mysql.jdbc.Driver</property>
<propertyname="connection.url">jdbc:mysql://localhost:3306/sshtest</property>
<propertyname="connection.username">root</property>
<propertyname="connection.password">00000000</property>
<!--JDBCconnectionpool-->
<propertyname="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<propertyname="hibernate.c3p0.max_size">20</property>
<propertyname="hibernate.c3p0.min_size">5</property>
<propertyname="hibernate.c3p0.timeout">120</property>
<propertyname="hibernate.c3p0.max_statements">100</property>
<propertyname="hibernate.c3p0.idle_test_period">120</property>
<propertyname="hibernate.c3p0.acquire_increment">2</property>
<propertyname="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<!--SQLdialect-->
<propertyname="dialect">org.hibernate.dialect.MySQLDialect</property>
<propertyname="current_session_context_class">thread</property>
<propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<propertyname="show_sql">true</property>
<!--<propertyname="hbm2ddl.auto">create</property>-->
<mappingresource="com/ergal/hibernate/pojo/User.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/Artist.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/Category.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/FileType.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/MyFile.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/MyLocation.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/MyPackage.hbm.xml"/>
<mappingresource="com/ergal/hibernate/pojo/MyPic.hbm.xml"/>
</session-factory>
</hibernate-configuration>
下面写一个类Test.java
packagecom.ergal;
importjava.io.File;
importjava.io.IOException;
importjavax.xml.parsers.DocumentBuilder;
importjavax.xml.parsers.DocumentBuilderFactory;
importjavax.xml.parsers.ParserConfigurationException;
importorg.w3c.dom.Document;
importorg.w3c.dom.Element;
importorg.w3c.dom.Node;
importorg.w3c.dom.NodeList;
importorg.w3c.dom.Text;
importorg.xml.sax.SAXException;
publicclassTest
...{
publicstaticvoidmain(String[]args)throwsIOException
...{
try
...{
DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
DocumentBuilderbuilder=factory.newDocumentBuilder();
Filef=newFile("bin/hibernate.cfg.xml");
//得到文档
Documentdoc=builder.parse(f);
//得到根元素
Elementroot=doc.getDocumentElement();
}catch(ParserConfigurationExceptione)
...{
e.printStackTrace();
}catch(SAXExceptione)...{
e.printStackTrace();
}
}
}
这里面的root就是获得的根元素 来看看它的名字是什么 Node里有getNodeName的方法
Element里有 getTagName的方法 在这里都可以用 在后面添加以下代码:
//获得根元素的名字
StringrootElementName=root.getNodeName();
//StringrootElementName=root.getTagName();
System.out.println(rootElementName);
Console 里就会打印
hibernate-configuration
现在 要获得hibernate-configuration下的所有子节点 (事实上只有一个) 就要用到 NodeList这个接口和
Element的getChildNodes()这个方法
添加以下代码
//得到子节点的集合
NodeListchildrenNodes=root.getChildNodes();
//得到字节点的个数
intnodeSize=childrenNodes.getLength();
System.out.println(nodeSize);
//在for中得到各个子节点
for(inti=0;i<nodeSize;i++)
...{
Nodechild=childrenNodes.item(i);
System.out.println(child.getNodeName()+" "+child.getNodeValue());
}
在Console 打印的结果是
3
#text
session-factory
null
#text
很明显了 这就可以解释那些Node的子接口分别的作用了 Elemnet 表示元素 这里只有session-factory
另外其他空白区域的就是 Text 它的nodeName 就是#text Hibernate的session-factory 的nodeValue为null
所有的内容都可以找到相应的一种Node 如 Element Text 还有注释Comment 等等
这些在Node的API中有明确的定义 如下:
包括属性 nodeName
、nodeValue
和 attributes
作为一种获取节点信息的机制,无需向下强制转换为特定的派生接口。在没有对特定的 nodeType
(如 Element
的 nodeValue
或 Comment
的 attributes
)的属性的明显映射的情况下,这将返回 null
。注意,特定的接口可能包含其他更方便的机制来获取和设置相关信息。
nodeName
、nodeValue
和 attributes
的值将根据以下节点类型的不同而不同。
Interface
nodeName
nodeValue
attributes
Attr |
与 Attr.name 相同 |
与 Attr.value 相同 |
null |
CDATASection |
"#cdata-section" |
与 CharacterData.data 相同,CDATA 节的内容 |
null |
Comment |
"#comment" |
与 CharacterData.data 相同,该注释的内容 |
null |
Document |
"#document" |
null |
null |
DocumentFragment |
"#document-fragment" |
null |
null |
DocumentType |
与 DocumentType.name 相同 |
null |
null |
Element |
与 Element.tagName 相同 |
null |
NamedNodeMap |
Entity |
entity name |
null |
null |
EntityReference |
引用的实体名称 |
null |
null |
Notation |
notation name |
null |
null |
ProcessingInstruction |
与 ProcessingInstruction.target 相同 |
与 ProcessingInstruction.data 相同 |
null |
Text |
"#text" |
与 CharacterData.data 相同,该文本节点的内容 |
null |
在所有的Node里面 现在看来 对我们有用的只有Element 在这里就是session-factory
因此可以加上一个条件
Nodechild=childrenNodes.item(i);
if(childinstanceofElement)
...{
System.out.println(child.getNodeName());
}
也可以把这个Node转换为Element来分析
这样Console得到的结果就是
因为已经知道一共有3个节点 而且在session-factory这个节点前有#text 后面也是#text 中间才是有用的元素
所以这里可以用另外一种方法来得到session-factory这个节点
NodefirstNode=root.getFirstChild();
NodesecondNode=firstNode.getNextSibling();
效果是一样的
现在可以来遍历sessionFactory里的元素
再看看hibernate.cfg.xml中 在session-factory 中 有好几种Node 有注释 有空白 有元素嵌套(或者说元素里面还有)元素
现在这么写来遍历sessionFactory里的元素
//得到session-factory的子节点的集合
NodeListthirdNode=secondNode.getChildNodes();
//得到子节点的数量
inttNodeLength=thirdNode.getLength();
//循环得到子节点
for(intj=0;j<tNodeLength;j++)
...{
NodethChildNode=thirdNode.item(j);
if(thChildNodeinstanceofElement)
...{
System.out.println(thChildNode.getNodeName());
}
}
在Console里的结果就是
property
property
property
property
property
property
property
property
property
property
property
property
property
property
property
property
mapping
mapping
mapping
mapping
mapping
mapping
mapping
mapping
这是把空白和注释都过滤掉了的剩下的元素 其实完全可以再细化一下
因为mapping是只有属性的 而property是既有属性也有子节点的(差点写成了子元素)
另:在不知道属性名的情况下是无法获得属性的 Node里的方法getAttributes()返回的是NameNodeMap
这个和NodeList的区别是 只有在有Name的情况下才能访问 就是此集合是通过名称访问节点的集合
而Element里的方法也都需要知道属性名 难道就只有一直 if else 下去来遍历
虽然hibernate是用的Dom4j 我还是看了一下Hibernate的源代码
在Configuration有如下一个方法
privatevoidaddProperties(Elementparent)...{
Iteratoriter=parent.elementIterator("property");
while(iter.hasNext())...{
Elementnode=(Element)iter.next();
Stringname=node.attributeValue("name");
Stringvalue=node.getText().trim();
log.debug(name+"="+value);
properties.setProperty(name,value);
if(!name.startsWith("hibernate"))...{
properties.setProperty("hibernate."+name,value);
}
}
Environment.verifyProperties(properties);
}
这样把键值都取出来再交给parseSessionFactory()方法去解析
parseSessionFactory()的代码如下
privatevoidparseSessionFactory(ElementsfNode,Stringname)...{
Iteratorelements=sfNode.elementIterator();
while(elements.hasNext())...{
Elementsubelement=(Element)elements.next();
StringsubelementName=subelement.getName();
if("mapping".equals(subelementName))...{
parseMappingElement(subelement,name);
}
elseif("class-cache".equals(subelementName))...{
StringclassName=subelement.attributeValue("class");
AttributeregionNode=subelement.attribute("region");
finalStringregion=(regionNode==null)?className:regionNode.getValue();
booleanincludeLazy=!"non-lazy".equals(subelement.attributeValue("include"));
setCacheConcurrencyStrategy(className,subelement.attributeValue("usage"),region,includeLazy);
}
elseif("collection-cache".equals(subelementName))...{
Stringrole=subelement.attributeValue("collection");
AttributeregionNode=subelement.attribute("region");
finalStringregion=(regionNode==null)?role:regionNode.getValue();
setCollectionCacheConcurrencyStrategy(role,subelement.attributeValue("usage"),region);
}
elseif("listener".equals(subelementName))...{
parseListener(subelement);
}
elseif("event".equals(subelementName))...{
parseEvent(subelement);
}
}
}
然后在把不同的元素 交给不同的处理器 比如 mapping就用parseMappingElement( subelement, name );
也是用if else的方法来取得值的 看来我的想的也八九不离十
好 回到我的例子中 我就不一一按属性的名来获得值了 就直接获得所有的元素的值 只有属性的mapping就可以很方便的获得属性值
于是修改如下 并且根据Text的getData 方法(确切的说是CharactorData的方法)等 来获取每个元素的属性值和子节点的text
//得到session-factory的子节点的集合
NodeListthirdNode=secondNode.getChildNodes();
//得到子节点的数量
inttNodeLength=thirdNode.getLength();
//循环得到子节点
for(intj=0;j<tNodeLength;j++)
...{
NodethChildNode=thirdNode.item(j);
//得到有子节点的元素
if(thChildNodeinstanceofElement&&thChildNode.hasChildNodes())
...{
//将节点转换为元素
ElementthChildElement=(Element)thChildNode;
//获得text
TexttextNode=(Text)thChildElement.getFirstChild();
//得到该元素的值这里的trim方法可以去掉前后的空白
Stringtext=textNode.getData().trim();
System.out.println(text);
}
//得到没有子节点只有属性的mapping元素
elseif(thChildNodeinstanceofElement&&!thChildNode.hasChildNodes())
...{
//将节点转换为元素
ElementthChildElement=(Element)thChildNode;
//获得属性的值
Stringtext=thChildElement.getAttribute("resource");
System.out.println(text);
}
}
这样Console的结果就是
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/sshtest
root
00000000
org.hibernate.connection.C3P0ConnectionProvider
20
5
120
100
120
2
org.hibernate.transaction.JDBCTransactionFactory
org.hibernate.dialect.MySQLDialect
thread
org.hibernate.cache.NoCacheProvider
true
com/ergal/hibernate/pojo/User.hbm.xml
com/ergal/hibernate/pojo/Artist.hbm.xml
com/ergal/hibernate/pojo/Category.hbm.xml
com/ergal/hibernate/pojo/FileType.hbm.xml
com/ergal/hibernate/pojo/MyFile.hbm.xml
com/ergal/hibernate/pojo/MyLocation.hbm.xml
com/ergal/hibernate/pojo/MyPackage.hbm.xml
com/ergal/hibernate/pojo/MyPic.hbm.xml
这些是最基本的DOM解析方法
分享到:
相关推荐
1 X1 XML基础ML基础1 XML基础1 XML基础1 XML基础1 XML基础1 XML基础1 XML基础
XML基础知识大全..XML基础知识大全
XML基础实例 XML基础XML基础实例 XML基础
张孝祥老师的xml基础的课堂ppt!!欢迎下载
xml基础教程ppt是xml的一些有关的基础知识和例子,
新手可以查看这个文档,xml基础.pdf
xml基础,xml语言的定义,xml的数据岛,xml结点的设置、获取。
XML基础 xml基础资料是一本很好的书籍
关于XML的课件文档,主要是基础,包括XML基础、XSL、SAX、数据岛、XPath、CSS修饰XML文档等等。
这是我学习xml的笔记。xml基础实验收集,适合xml初学者学习,希望能帮到初学者。
XML基础实例 数据岛XML基础实例 数据岛
包括XML语法和概述、数据岛、xpath查询等
-XML基础教程源码-code-XML基础教程源码-code
xml是w3c组织提出的一种可扩展性的标记语言,是独立于计算机平台的数据交换规范,PPT主要包括了xml概述,xml语法,文档类型定义,css,xslt,文档对象模型,xml与数据库等知识篇章,同时提供相关章节的例题源代码
Xml基础教程 高怡新版 ppt 源码
xml安全基础xml安全基础xml安全基础xml安全基础xml安全基础
张孝祥XML基础 成都张孝祥 xml 张孝祥XML基础 张孝祥XML基础 传智播客
本书覆盖XML结构以及与之相关的安全技术基础知识,包括:XML签名、XML加密和XML密钥关联规范;本资源不仅包含你所需要的概念性信息,而且还包含你所需要的实用技术,从而可使你成功运用这一数据结构语言。理解RSA的...
《XML 基础教程》系统地阐述了XML的基本概念和语法规则,介绍了如何用DTD与XML Schema来确保XML文档的有效性,讲述了使用CSS与XSL样式表来显示和转换XML文档的各个步骤,探讨了使用DSO与DOM访问XML文档的各种方法。...
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/css" href="cd_catalog.css"?> <TITLE>Empire Burlesque <ARTIST>Bob Dylan <COUNTRY>USA <COMPANY>Columbia <PRICE>10.90 <YEAR>1985 ...