Skip to content

Categories:

DOM4J官方快速入门(译文)中文详解

官方地址:http://www.dom4j.org/dom4j-1.6.1/guide.html

Dom4j 快速入门

Parsing XML (xml 解析)

以下例子演示了如何使用SAX解析器解析XML,返回一个DOM 模型的对象,即DOCUMENT.

有了DOCUMENT我们就可以进行文档操作了。

import java.net.URL;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
 
public class Foo {
 
public Document parse(URL url) throws DocumentException {
	// 以DOM4J默认的SAX解析器解析
        SAXReader reader = new SAXReader();
	// read函数的形参可以是url 也可以是 File类型,也可以是STRING类型的相对或绝对路径
        Document document = reader.read(url);
        return document;
    }
}
 
 Using Iterators(使用迭代器)
该部分演示了如何使用迭代器(迭代器是一种设计模式,可用于遍历如集合、数组等)进行文档的遍历。以下演示了获得三种的迭代器。
 
public void bar(Document document) throws DocumentException {
	// 获得根节点
	Element root = document.getRootElement();
 
	// i为根节点孩子节点的迭代器
	for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
		Element element = (Element) i.next();
		// do something
		System.out.println(element.getName());
	}
 
	// 名为“student1”节点以下孩子节点的迭代器
	for ( Iterator i = root.elementIterator("student1" ); i.hasNext(); ) {
		Element foo = (Element) i.next();
		// do something
		System.out.println(foo.getText());
	}
 
	// 根节点属性的迭代器
	for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
		Attribute attribute = (Attribute) i.next();
		// do something
		System.out.println(attribute.getValue());
	}
 }

————————————————————————————————————————

以下是:foo.xml

<?xml version="1.0" encoding="gb2312"?>
<foo id="1111" fooname="test">
	<student sn="01"><name>张三</name><age>18</age></student>
	<student sn="02"><name>李四</name><age>20</age></student>
	<student1 sn="03">小翁</student1>
</foo>

————————————————————————————————————————

Main函数中执行如下命令:

	Foo foo = new Foo();
		Document doc ;
		//1.2 Using Iterators
		File file = new File("foo.xml");
		try {
			//parse  为以上1.1 部分的方法
			doc = foo.parse(file);
			foo.bar(doc);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	}

结果:
student
student
student1
小翁
1111
test

Powerful Navigation with Xpath(使用Xpth进行导航)

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。

具体可以参见http://www.w3school.com.cn/xpath/xpath_syntax.asp

注意:使用XPATH进行导航时,有时需要导入一个名jaxen-XXX.jar的包,该包可以在 官方DOM4J文件夹lib目录下有。

Dom4j XPath 表达式也以表示文档或文档树中的节点(如属性,元素,以及处理指令)。可以用一行简单的代码进行复杂的文档遍历。如下:

	public void barWithXPath(Document document) {
			// “//”表示任意路径节点 如 //name 任意名为name 的节点
		List<Node> list = document.selectNodes("//name");
		for (Node nodeTmp : list) {
			System.out.println(nodeTmp.getText());
		}
		//"//foo/student[2]" 表示带有foo路径下第二个student节点
		Node node = document.selectSingleNode("//foo/student[2]");
		// “@”表示属性
		String name = node.valueOf("@sn");
		System.out.println(name);
	}

————————————————————-

以下是:foo.xml

	<?xml version="1.0" encoding="gb2312"?>
<foo id="1111" fooname="test">
	<student sn="01"><name>张三</name><age>18</age></student>
	<student sn="02"><name>李四</name><age>20</age></student>
	<student1 sn="03">小翁</student1>
</foo>

————————————————————————————————————————

Main函数中执行如下命令:

	Foo foo = new Foo();
	Document doc ;
	//1.3 Powerful Navigation with Xpath
	File file = new File("foo.xml");
	try {
		doc = foo.parse(file);
		foo.barWithXPath(doc);
	} catch (DocumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

结果:
张三
李四
02

例如,如果你想获取一个XHTML中的所有超级链接,可以采用如下方式:

    public void findLinks(Document document) throws DocumentException {
 
        List list = document.selectNodes( "//a/@href" );
 
        for (Iterator iter = list.iterator(); iter.hasNext(); ) {
            Attribute attribute = (Attribute) iter.next();
            String url = attribute.getValue();
        }
	}

—————————————————————–

MyXhtml.xhtml文件

	<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<title>MyXhtml.xhtml</title>
	</head>
	<body>
		<a href="1">www.oseschool.com</a>
		<a href="2">2222</a>
		<a href="3">3333</a>
	</body>
</html>

—————————————————————–

注意:若要利用上述findLinks 函数得到MyXhtml.xhtml文件中的a标签中href的属性值,必须对代码进行一定的修改。主要是因为MyXhtml.xhtml文件中带有命名空间。

具体代码如下:

public Document parseWithNameSpace(File file) throws DocumentException {
	SAXReader reader = new SAXReader();
	Map map = new HashMap();
	//把文件中的所以命名空间先放入一个MAP中
	map.put("xmlns1", "http://www.w3.org/1999/xhtml");
	//设置命名空间
	reader.getDocumentFactory().setXPathNamespaceURIs(map);
	Document document = reader.read(file);
	return document;
}
public void findLinks(Document document) throws DocumentException {	//注意对要遍历的元素要加命名空间限制
	List list = document.selectNodes("//xmlns1:a/@href");
 
	for (Iterator iter = list.iterator(); iter.hasNext();) {
		Attribute attribute = (Attribute) iter.next();
		String url = attribute.getValue();
		System.out.println(url);
	}
}

————————————————————————————————————————

Main函数执行:

	Foo foo = new Foo();
	Document doc ;
	//1.3 Powerful Navigation with Xpath
	File file = new File("MyXhtml.xhtml");
	try {
		doc = foo.parseWithNameSpace(file);
		foo.findLinks(doc);
	} catch (DocumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

结果:
www.oseschool.com
2
3

Fast Looping(快速循环)

如果你要遍历一个较大的XML文档,那么我们推荐你使用快速循环(递归)方法,这样将避免创建迭代器对象带来的开销。如下:

	public void treeWalk(Document document) {
        treeWalk( document.getRootElement() );
    }
	//采用递归的方式
    public void treeWalk(Element element) {
        for ( int i = 0, size = element.nodeCount(); i < size; i++ ) {
            Node node = element.node(i);
		//判断是否是元素,如<test>11</test>即为元素
            if ( node instanceof Element ) {
                treeWalk( (Element) node );
            }
            else {
                // do something....打印元素中的文本内容
		System.out.println(node.getText());
            }
        }
	}

————————————————————-

以下是:foo.xml

<?xml version="1.0" encoding="gb2312"?>
<foo id="1111" fooname="test">
	<student sn="01"><name>张三</name><age>18</age></student>
</foo>

————————————————————————————————————————

Main函数执行:

	Foo foo = new Foo();
	Document doc ;
	//1.4 Fast Looping
	File file = new File("foo.xml");
	try {
		//parse方法为1.1 中 parse方法
		doc = foo.parse(file);
		foo.treeWalk(doc);
	} catch (DocumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

结果:
(空行)
(空行)
张三
18

分析:“(空行)”表示本行内容为空,或许很多人感到疑问,为什么会有两个空行了,由于

<foo id="1111" fooname="test">
	<student sn="01"><name>张三</name><age>18</age></student>
</foo>

以及后都出现了换行,故解析器认为有两个TEXT类型的节点。也就是把文件改为:

<foo id="1111" fooname="test"><student sn="01"><name>张三</name><age>18</age></student></foo>

所以节点在同一行,结果就不会有空行。

————————————————————————————————————————

 Creating a new XML document(创建一个新的XML文档)
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
 
public class Foo {
 
    public Document createDocument() {
        Document document = DocumentHelper.createDocument();
        Element root = document.addElement( "root" );
 
        Element author1 = root.addElement( "author" )
            .addAttribute( "name", "James" )
            .addAttribute( "location", "UK" )
            .addText( "James Strachan" );
 
        Element author2 = root.addElement( "author" )
            .addAttribute( "name", "Bob" )
            .addAttribute( "location", "US" )
            .addText( "Bob McWhirter" );
 
        return document;
    }
}

Writing a document to a file(写入一个文档到一个文件)

一种快速而简单地把文档写入到一个文件,即调用字符输出流的write方法。

  FileWriter out = new FileWriter( "foo.xml" );
  document.write( out );

如果你想要改变输出的格式,如宽松或紧凑的格式,而且你想要使用一些基本的字节或字符输出流,那么你可以使用XMLWriter类,如下。

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
 
public class Foo {
 
    public void write(Document document) throws IOException {
 
        // lets write to a file
        XMLWriter writer = new XMLWriter(
            new FileWriter( "output.xml" )
        );
        writer.write( document );
        writer.close();
 
        // 打印出Pretty的样式。即元素之间有换行。
        OutputFormat format = OutputFormat.createPrettyPrint();
        writer = new XMLWriter( System.out, format );
        writer.write( document );
 
        // 紧凑的格式,所有元素在一行
        format = OutputFormat.createCompactFormat();
        writer = new XMLWriter( System.out, format );
        writer.write( document );
    }
}

注意:如果按上述形式打印输出,是以计算机默认编码,进行写入操作,也就是如果在中文系统下,你读出的DOM,如果是UTF-8编码的,不会正确输出。所以建议用对上面的代码改进,如下:

	OutputFormat outFmt=new OutputFormat();
	outFmt.setEncoding("utf8");
 
	try
	{
		XMLWriter xmlWriter=new XMLWriter(new FileOutputStream("dom4jtest.xml"),outFmt);
		xmlWriter.write(doc);
 
		xmlWriter.flush();
		xmlWriter.close();
	}

上面最大改变是把FileWriter->FileOutputStream.然后使用OutputFormat设定编码。

Converting to and from Strings(转换字符串)

如果你有一个文档对象的引用或任何其他像属性或元素的节点,那么你可以把他们转换为一种默认的XML文本,通过调用 asXML 方法。

	Document document = ...;
	String text = document.asXML();

如果你有些XML的文本字符串,你可以把它再转换回文档对象,通过使用帮助方法DocumentHelper.parseText()

	String text = "<person> <name>James</name> </person>";
	Document document = DocumentHelper.parseText(text);
 Styling a Document with XSLT(使用XSLT格式一个文档)

要想在一个文档对象上运用一个XSLT可以直接调用SUN 的JAXP API(JAVA API FOR XML PROGRAM)。允许使用像Xalan或SAXON这样的任何XSLT引擎。这里有一个使用JAXP来创建transformer对象然后将XSLT运用在一个文档上。

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
 
import org.dom4j.Document;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
 
public class Foo {
 
    public Document styleDocument(
        Document document, 
        String stylesheet
    ) throws Exception {
 
        // load the transformer using JAXP
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer( 
            new StreamSource( stylesheet ) 
        );
 
        // now lets style the given document
        DocumentSource source = new DocumentSource( document );
        DocumentResult result = new DocumentResult();
        transformer.transform( source, result );
 
        // return the transformed document
        Document transformedDoc = result.getDocument();
        return transformedDoc;
    }
}

———————————————————————————————————————-

Catalog.XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
</catalog>

———————————————————————————————————————

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
    <tr bgcolor="#9acd32">
      <th align="left">Title</th>
      <th align="left">Artist</th>
    </tr>
    <xsl:for-each select="catalog/cd">
    <tr>
      <td><xsl:value-of select="title"/></td>
      <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

———————————————————————————————————————

Main函数:

	Foo foo = new Foo();
	Document doc ;
	//1.4 Fast Looping
	File file = new File("catalog.xml");
	try {
		doc = foo.parse(file);
		Document newDoc = foo.styleDocument(doc, "catalog.xsl");
		// 1.6 中的write方法
		foo.write(newDoc);
 
	} catch (DocumentException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

———————————————————————————————————————

结果:

<?xml version="1.0" encoding="UTF-8"?>
 
<html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th align="left">Title</th>
        <th align="left">Artist</th>
      </tr>
      <tr>
        <td>Empire Burlesque</td>
        <td>Bob Dylan</td>
      </tr>
    </table>
  </body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<html><body><h2>My CD Collection</h2><table border="1"><tr bgcolor="#9acd32"><th align="left">Title</th><th align="left">Artist</th></tr><tr><td>Empire Burlesque</td><td>Bob Dylan</td></tr></table></body></html>

分析:结果中有一个为Pretty的样式,一个为compact的样式。还生成了一个output.xml

Posted in java.


0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.