Dom4j 学习笔记
The dom4j Project Homepage: http://www.dom4j.org
Loading XML Data
以下代码从File中或一个URL中读取一个XML文件,并产生一个Document对象。一个Document对象表示了内存中的一棵XML树,可以在这个XML树中进行遍历、查询、修改等操作。
import java.io.*;
import java.net.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
public class XMLLoader {
private Document doc = null;
public void parseWithSAX(File file)
throws MalformedURLException, DocumentException {
SAXReader xmlReader = new SAXReader();
this.doc = xmlReader.read(file);
return;
}
public void parseWithSAX(URL url)
throws MalformedURLException, DocumentException {
SAXReader xmlReader = new SAXReader();
this.doc = xmlReader.read(url);
return;
}
}
QName and Namespace
QName对象表示了一个XML元素或属性的qualified name,即一个namespace和一个local name的二元组。
Namespace对象表示了QName二元组中的namespace部分,它由prefix和URI两部分组成。
/******************** SAMPLE XML FILE *************************
<heavyz:Sample
xmlns:heavyz="http://www.heavyzheng.com/schema/sample.xsd">
<heavyz:HelloWorld/>
</heavyz:Sample>
*************************************************************/
public void printRootQNameInfo(Document doc) {
Element root = doc.getRootElement();
QName qname = root.getQName();
System.out.println("local name : " + qname.getName());
System.out.println("namespace prefix: " + qname.getNamespacePrefix());
System.out.println("namespace URI : " + qname.getNamespaceURI());
System.out.println("qualified name : " + qname.getQualifiedName());
return;
}
/************************* OUTPUT *****************************
localname : Sample
namespace prefix: heavyz
namespace URI : http://www.heavyzheng.com/schema/sample.xsd
qualified name : heavyz:Sample
*************************************************************/
可以调用Namespace(String prefix, String uri)构造方法构造一个新的Namespace对象;也可以调用Namespace.get(String prefix, String uri)静态方法获得一个新的Namespace对象。
可以调用QName(String name)构造方法构造一个没有namespace的qualified name;或者调用QName(String name, Namespace namespace)构造方法构造一个有namespace的qualified name。
Navigating Through an XML Tree
对Document对象调用getRootElement()方法可以返回代表根节点的Element对象。拥有了一个Element对象后,可以对该对象调用elementIterator()方法获得它的子节点的Element对象们的一个iterator。使用(Element)iterator.next()方法遍历一个iterator并把每个取出的元素转化为Element类型。
通过递归的方法,以下代码可以根据Document对象打印出完整的XML树。
public void printXMLTree(Document doc) {
Element root = doc.getRootElement();
printElement(root,0);
return;
}
private void printElement(Element element, int level) {
// print indent
for (int i=0; i<level; i++) {
System.out.print(" ");
}
System.out.println(element.getQualifiedName());
Iterator iter = element.elementIterator();
while (iter.hasNext()) {
Element sub = (Element)iter.next();
printElement(sub,level+2);
}
return;
}
Getting Information from an Element
可以通过Element类提供的方法访问一个XML元素中含有的信息:
Method |
Comment |
getQName() |
元素的QName对象 |
getNamespace() |
元素所属的Namespace对象 |
getNamespacePrefix() |
元素所属的Namespace对象的prefix |
getNamespaceURI() |
元素所属的Namespace对象的URI |
getName() |
元素的local name |
getQualifiedName() |
元素的qualified name |
getText() |
元素所含有的text内容,如果内容为空则返回一个空字符串而不是null |
getTextTrim() |
元素所含有的text内容,其中连续的空格被转化为单个空格,该方法不会返回null |
attributeIterator() |
元素属性的iterator,其中每个元素都是Attribute对象 |
attributeValue() |
元素的某个指定属性所含的值 |
elementIterator() |
元素的子元素的iterator,其中每个元素都是Element对象 |
element() |
元素的某个指定(qualified name或者local name)的子元素 |
elementText() |
元素的某个指定(qualified name或者local name)的子元素中的text信息 |
getParent |
元素的父元素 |
getPath() |
元素的XPath表达式,其中父元素的qualified name和子元素的qualified name之间使用"/"分隔 |
isTextOnly() |
是否该元素只含有text或是空元素 |
isRootElement() |
是否该元素是XML树的根节点 |
要取出Element对象中某个属性的信息,可以调用attributeIterator()方法获得一个Attribute对象的iterator,然后再遍历它。也可以直接调用attributeValue()方法获得指定属性的值。该方法接受四种类型的参数:
- attributeValue(QName qname):通过指定qualified name获得属性值,如果无法找到指定的属性,则返回null。
- attributeValue(QName qname, String defaultValue):通过指定qualified name获得属性值,如果无法找到指定的属性,则返回defaultValue。
- attributeValue(String name):通过指定local name获得属性值,而忽略属性的namespace,如果无法找到指定的属性,则返回null。
- attributeValue(String name, String defaultValue):通过指定local name获得属性值,而忽略属性的namespace,如果无法找到指定的属性,则返回defaultValue。
对于一个Attribute对象,可以使用它的以下方法访问其中的信息:
Method |
Comment |
getQName() |
属性的QName对象 |
getNamespace() |
属性所属的Namespace对象 |
getNamespacePrefix() |
属性所属的Namespace对象的prefix |
getNamespaceURI() |
属性所属的Namespace对象的URI |
getName() |
属性的local name |
getQualifiedName() |
属性的qualified name |
getValue() |
属性的值 |
Writing an XML Tree to OutputStream
Dom4j通过XMLWriter将由Document对象表示的XML树写入一个文件,并使用OutputFormat格式对象指定写入的风格和编码方法。调用OutputFormat.createPrettyPrint()方法可以获得一个默认的pretty print风格的格式对象。对OutputFormat对象调用setEncoding()方法可以指定XML文件的编码方法。
public void writeTo(OutputStream out, String encoding)
throws UnsupportedEncodingException, IOException {
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("gb2312");
XMLWriter writer = new XMLWriter(System.out,format);
writer.write(doc);
writer.flush();
return;
}
Creating an XML Tree
使用DocumentFactory对象创建一个空的Document对象。DocumentFactory对象由DocumentFactory.getInstance()静态方法产生。对Document对象调用addElement()方法将创建XML根节点,并将该节点返回。也可以手工创建一个Element对象并调用Document.setRootElement()方法把它设置为根节点
import org.dom4j.DocumentFactory;
import org.dom4j.Document;
import org.dom4j.Element;
public class XMLSaver {
private DocumentFactory factory = null;
private Document doc = null;
private Element root = null;
public XMLSaver() {
factory = DocumentFactory.getInstance();
doc = factory.createDocument();
}
public Element generateRoot(String name) {
root = doc.addElement(name);
return root;
}
public Element generateRoot(QName qname) {
root = doc.addElement(qname);
return root;
}
public Element generateRoot(Element element) {
doc.setRootElement(element);
root = element;
return root;
}
}
Adding Information into an Element
Element通过addElement()为自己增加一个子节点到当前所有子节点的后面。该方法可以接受三种不同类型的参数:(QName qname)、(String name)或者(String qualifiedName, String namespaceURI)。该方法返回增加的子节点的Element对象。
Element通过addAttribute()为自己增加属性。该方法可以接受两种不同类型的参数:(QName qname, String value)或者(String name, String value)。该方法返回自身的Element对象。
Element通过addText()为自己增加文本内容。该方法只接受String类型参数,并返回自身的Element对象。
public void addAuthors(Element bookElement) {
Element author1 = bookElement.addElement("author");
author1.addAttribute("name","Toby");
author1.addAttribute("location","Germany");
author1.addText("Tobias Rademacher");
Element author2 = bookElement.addElement("author");
author2.addAttribute("name","James");
author2.addAttribute("name","UK");
author2.addText("James Strachan");
return;
}
Deleting Elements and Attributes
要删除XML树上的一棵子树,首先要找到该子树的根节点,然后对该节点调用detach()方法。注意:如果对根节点调用了detach()方法,将导致该XML树不再完整(一个XML文件需要有且仅有一个根节点)。
public void deleteSubtree(Element subtreeRoot) {
subtreeRoot.detach();
return;
}
要清除Element下的所有子节点(包括Element和text),可以对该Element调用clearContent()方法。该方法不会清除Element的属性。
要清除Element下的某个Attribute,首先要获得该Attribute对象,然后把它作为参数调用Element的remove()方法。
Updating an Attribute
要更新一个属性的内容,首先要获得该Attribute对象,然后可以调用setNamespace()方法更新它所属的namespace;调用setValue()方法更新它的属性值。
Updating an Element's Text
可以对一个Element对象调用isTextOnly()方法判断它是否只含有text或者是空节点。对Element对象调用addText()方法将把一个字符串附加到Element中,但不会修改它原来拥有的text或者子节点。如果Element是isTextOnly(),要修改原来含有的text,可以先调用clearContent(),再调用addText()并把新值传入。
public void updateText(Element element, String newText) {
if (element.isTextOnly()) {
element.clearContent();
element.addText(newText);
}
return;
}
Ajax读书笔记070417
再读Ajax,大体可以分成3个部分:
a: 在浏览器端,使用JavaScript获取必要的信息和数据,然后通过XMLHttpRequest以异步的方式将数据传递给服务器端。
b: 在服务器端(servlet),获取传递的数据,然后经过一系列的分析处理,将要返回给浏览器的信息以字符串或者XML的形式输出到浏览器。
c: 在浏览器端,接收到服务器返回的字符串或者XML,对字符串或者XML解析,并将相应的内容显示在页面上。
通过上面我们可以认为Ajax的关键部分是b和c,如果对Java编程有基本的了解,组织数据并写页面难度并不大,那么难点就集中在c,解析服务器返回的内容,并显示在页面上,这需要对JavaScript和DOM有一定的经验,这部分也是Ajax出彩的地方。
一、XMLHttpRequest的四个状态(readyState)
0: 未初始化 对象已经创建,尚未调用open()
1: 已初始化 调用open()方法以后
2: 发送数据 调用send()方法以后
3: 数据发送中 在已经接到部分数据,但尚未接收完成
4: 完成 数据全部接收完成
二、获得XMLHttpRequest返回数据
1. reponseText 将相应信息作为字符串返回
2. responseXML 将响应信息格式作为XMLDOM对象返回
3. responseBody 将响应信息以unsigned byte数组的形式返回
4. responseStream 将响应信息以IStream对象的形式返回
三、XMLHttpRequest的status状态
200: 表明Http状态是良好的
404:表明请求的页面没有找到
其它的可参考http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
四、采用JDOM定义XML对象
1、从http://www.jdom.org下载jdom.jar,并放在WEB-INF/lib目录下。
2、代码示例:
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
public String createJdomXML(int key) throws IOException {
Document document = new Document( );
//创建根节点
Element root = new org.jdom.Element("converted-values");
document.setRootElement(root);
//创建节点
org.jdom.Element element = new org.jdom.Element("decimal");
//设置节点内容
element.addContent(Integer.toString(key));
//将节点添加到根节点下
root.addContent(element);
//定义其他节点
element = new org.jdom.Element("hexadecimal");
element.addContent("0x" + Integer.toString(key, 16));
root.addContent(element);
element = new org.jdom.Element("octal");
element.addContent("0" + Integer.toString(key, 8));
root.addContent(element);
element = new org.jdom.Element("hyper");
element.addContent("&0x" + Integer.toString(key, 16));
root.addContent(element);
element = new org.jdom.Element("binary");
element.addContent(Integer.toString(key, 2) + "B");
root.addContent(element);
//将Document以字符流的方式输出
XMLOutputter outputter = new XMLOutputter( );
return outputter.outputString(document);
}
五、采用dom4j定义XML对象
1、通过站点http://www.dom4j.org/download.html下载dom4j,并保存到WEB-INF/lib
2、代码示例如下所示:
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public String createDom4jXML(int key) throws IOException {
//定义document对象
Document document = DocumentHelper.createDocument( );
//定义根节点
Element root = document.addElement("converted-values");
//定义其他节点
Element element = root.addElement("decimal").addText(Integer.toString(key));
element = root.addElement("hexadecimal").addText("0x" + Integer.toString(key, 16));
//生成字符串流
StringBuffer xmlDoc = null;
StringWriter sw = new StringWriter( );
OutputFormat outformat = OutputFormat.createPrettyPrint( );
XMLWriter writer = new XMLWriter(sw, outformat);
writer.write(document);
writer.close( );
xmlDoc = sw.getBuffer( );
return xmlDoc.toString( );
}
六、使用JavaScript解析XML
1、不同的浏览器采用的XML解析方法也不同,首先要区分当前浏览器的类型
function callback( ) {
if (req.readyState==4) {
if (req.status == 200) {
//非IE浏览器,如Firefox Mozilla Safari
if (window.XMLHttpRequest) {
nonMSPopulate( );
}
//Microsoft浏览器IE
else if (window.ActiveXObject) {
msPopulate( );
}
}
}
}
2、在IE浏览器中解析XML
function msPopulate()
{
//获得server返回的字符流
var resp = req.responseText;
//定义xml解析对象
var xmlDoc = new ActionXObject("Microsoft.XMLDOM");
xmlDoc.async="false"'
xmlDoc.loadXML(resp);
//根据名称获得对象数组
dec = xmlDoc.getElementsByTagName('decimal');
//获得第一个节点的内容
value = dec[0].firstChild.data;
}
3、在非IE浏览器中解析XML
function nonMSPopulate()
{
//获得返回的内容
var resp = req,responsText;
//定义解析对象
var parser = new DOMParser();
decVal = dom.getElementsByTagName("decimal");
value = decVal[0].childNodes[0].nodeValue;
}