`
rock
  • 浏览: 56534 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java解析xml

阅读更多

xml在java应用相当广泛,是各种框架配置文件的首先载体,典型的SSH架构如果没有xml, 。。。。。。

下面就分析一下java是如何解析xml的。

先说一下DTD(document type definition),它为文档结构制定了一套规则。

常用的是对ELEMENT和ATTLIST的定义,

ELEMENT的定义为:  <!ELEMENT menu (item)*> 即menu元素包含0或多个item元素

内容的规则如下:

E*                                                 0或多个E

E+                                                 1或多个E

E?                                                  0或1个E

E1|E2|E3.....|En                             n个元素中的一个

E1,E2,E3,.....,En                             n个元素按顺序排列

#PCDATA                                        文本

(#PCDATA|E1|E2|....|En)*              0或多个任意顺序的文本或元素

ANY                                                允许任意子元素

EMPTY                                            不允许有子元素

--------------------------------------------------------------------------------

ATTLIST的定义为:  <!ATTLIST element attribute_name type default > 即element名,属性名,类型,默认值

内容的规则如下:

类型                                   含义

CDATA                             任意的字符串

(A1|A2|A3|....|An)            多个A之一

NMTOKEN,NMTOKENS      1或多个名字标记

ID                                    一个唯一的ID

IDREF,IDREFS                 1或多个唯一ID的引用

ENTITY,ENTITIES            1或多个未经解析的实体

……………………                ……………………

默认值                                  含义

#REQUIRED                      属性是必须的

#IMPLIED                         属性是可选的

A                                      属性是可选的,若未指定,解析器报告的属性的是A

#FIXED A                         属性只能是A,不管有没有指定

 

以school.dtd为例;

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT school (class*)>
<!ELEMENT class (grade, count, teacher?)>
<!ELEMENT grade (#PCDATA)>
<!ELEMENT count (#PCDATA)>
<!ELEMENT teacher (#PCDATA)>
<!ATTLIST class
 type (big | small | normal) "normal"
 autoextend (true | false) "true"
>

对应的xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE school SYSTEM "E:\NEUSOFT\学习资料\XML\school.dtd">
<school>
 <class type="big" autoextend="true">
  <grade>3</grade>
  <count>50</count>
  <teacher>wang</teacher>
 </class>

<class autoextend="true">
  <grade>2</grade>
  <count>40</count>
 </class>

</school>

 

其中 class的type和autoextend属性默认值是"big","true",子元素teacher为可选

 

dtd文件在xml中的声明有两种方式,一种是如上所示的 system 声明,还有一种用public声明的方式

如:<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
           "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

 

关于属性的设置,一个通常的经验法则是只在作为修改值的解释时使用,而不是在指定值时使用。不过也有其他的法则,如hibernate把参数主要定义为属性,html中把不显示在网页上的定义为属性,等等,可以根据自己的需要定义。

 

java库提供了两种解析器:DOM(Document Object model)和SAX(Simple API for Xml)

 

以DOM为例:

package com.java.xml;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

public class ParseSchool {

 /**
  * @param args
  *            void
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub

  ParseSchool ps = new ParseSchool();
  try {
   ps
     .parseXMLSchool("E:/Workspace/javaTest/src/com/java/xml/school.xml");
  } catch (ParserConfigurationException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SAXException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 public Document getDocument(String url)
   throws ParserConfigurationException, SAXException, IOException {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  factory.setValidating(true); // 打开dtd验证
  factory.setIgnoringElementContentWhitespace(true);// 忽略空白符
  factory.setIgnoringComments(true); // 忽略注释

  DocumentBuilder builder = factory.newDocumentBuilder();
  File f = new File(url);
  return builder.parse(f);

 }

 public void parseXMLSchool(String url) throws ParserConfigurationException,
   SAXException, IOException {
  Document document = getDocument(url);
  Element root = document.getDocumentElement();
  System.out.println("root element :" + root.getTagName());
  NodeList children = root.getChildNodes(); // 取得子元素列表
  for (int i = 0; i < children.getLength(); i++) {
   Element element = (Element) (children.item(i));

   System.out.println(element.getTagName() // 取得element的attributes
     + ": type=" + element.getAttribute("type")
     + " autoextend:"
     + element.getAttribute("autoextend"));
   NodeList children2 = element.getChildNodes();
   for (int j = 0; j < children2.getLength(); j++) {
    Node node = children2.item(j); // 分别读取子元素
    Element element2 = (Element) node;
    Text t = (Text) node.getFirstChild(); // element
              // 的文本内容是下一个字元素,获取后将其(node)转换成Text
    System.out.println(element2.getTagName() + ":" + t.getData());
   }

  }

 }

}
运行结果为:

root element :school
class: type=big autoextend:true
grade:3
count:50
teacher:wang
class: type=normal autoextend:true
grade:2
count:40

 

使用XPath来定位信息,代码如下:

public void testXPath(Document document) throws XPathExpressionException {
  XPathFactory xPathFactory = XPathFactory.newInstance(); // 创建XPathFactory
  XPath xPath = xPathFactory.newXPath(); // 实例化XPath
  String count = xPath.evaluate("/school/class[1]/count", document); // 取得子元素count值
  String classType = xPath.evaluate("/school/class[1]/@type", document);// 取得属性type的值
  int classNum = ((Number) xPath.evaluate("count(school/class)",
    document, XPathConstants.NUMBER)).intValue(); // 取得子元素class的个数,使用了XPathConstants提供的属性参数
  System.out.println("class[1]: count = " + count + ",classtype="
    + classType);
  System.out.println("classNum=" + classNum);

  Node class1Node = (Node) xPath.evaluate("/school/class[1]", document,
    XPathConstants.NODE); // 取得第一个class
  String countOfClass1 = xPath.evaluate("/school/class[2]/count", class1Node); // 直接从class1Node中取值,/表示树根部位

  System.out.println("count of class2 =" + countOfClass1);
 }

关于红色部分,class1Node节点应该存放第一个class的信息,但是可以从中取到第二个class的count值。用debug查看其对象信息,里面的信息很乱,没有的看出什么结果,希望明白这一块的朋友给与指点,^~^.

 

DOM解析器读入的是一个完整的xml文档,对于大多数应用DOM都运行的很好,但是如果文档很大,就显得效率低下了。

SAX解析器在解析xml输入的构件时报告事件,但不会对文档进行存储,DOM就是在SAX基础上建立起来的。主要就是对

SAXParser类parse(source,handler)方法中handler的重写。

 

DOM4J是一个使用相当广泛的xml解析工具,hibernate就使用它来解析xml的,用起来也比较简单。

官方网站: http://www.dom4j.org/

学习资料连接:http://www-128.ibm.com/developerworks/cn/xml/x-dom4j.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics