这篇文章主要介绍sun的dom实现。 我们日常生活总用到最多就是document,node,element,Text等。 其继承关系如下。
经常地情况是一个xml只包含element和text对象。 由于他们都继承于Node,所以他们有相似的逻辑。唯一的不同是text是做为终结点,而element作为中间节点。这不正是树的一个很好的表述吗?因此xml的解析完全可以像树一样, 用递归算法。 以下是实现。
package com.rxyu.xml;
import java.io.File;
import java.io.IOException;
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.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
public class TestXMLParser {
/**
* @param args
*/
public static void main(String[] args) {
String strPath=TestXMLParser.class.getResource("test.xml").getPath();
try {
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.parse(new File(strPath));
printXML(doc);
} catch (ParserConfigurationException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
catch(SAXException e){
e.printStackTrace();
}
}
public static void printXML(Document doc){
//get Root
Element root=doc.getDocumentElement();
System.out.println(getNodeString(root,0));
}
public static String getAttrs(NamedNodeMap attrs){
String strAttrs=new String();
for(int i=0;i<attrs.getLength();i++){
Node ni=attrs.item(i);
String name=ni.getNodeName();
String value=ni.getNodeValue();
strAttrs +=" "+name+"=\""+value+"\"";
}
return strAttrs;
}
public static String getNodeString(Node node){
String curString=new String();
if(node instanceof Text){
Text text=(Text)node;
String strText=text.getData().trim();
if(strText!=null){
curString+= strText;
}
}
if(node instanceof Element){
Element eNode=(Element)node;
NamedNodeMap attrs=eNode.getAttributes();
String curTag=eNode.getTagName();
//traverse the children
NodeList children=eNode.getChildNodes();
//if you want to format, you need to jude the type of the son;
int length=children.getLength();
boolean hasElement=true;
if(length==1){
Node theChild=children.item(0);
if(theChild instanceof Text){
hasElement=false;
}
}
if(hasElement)
curString +="<"+curTag+getAttrs(attrs)+">\n";
else
curString +="<"+curTag+getAttrs(attrs)+">";
for(int i=0;i<children.getLength();i++){
Node child=children.item(i);
curString +=getNodeString(child);
}
//give the suffix
curString +="</"+curTag+">\n";
}
return curString;
}
public static String getNodeString(Node node,int level){
String curString=new String();
int curLevel=level;
if(node instanceof Text){
Text text=(Text)node;
String strText=text.getData().trim();
if(strText!=null){
curString+= strText;
}
}
if(node instanceof Element){
Element eNode=(Element)node;
NamedNodeMap attrs=eNode.getAttributes();
String curTag=eNode.getTagName();
//traverse the children
NodeList children=eNode.getChildNodes();
//if you want to format, you need to jude the type of the son;
int length=children.getLength();
boolean hasElement=true;
if(length==1){
Node theChild=children.item(0);
if(theChild instanceof Text){
hasElement=false;
}
}
if(hasElement)
curString +=Space.copySpace(2*curLevel)+"<"+curTag+getAttrs(attrs)+">\n";
else
curString +=Space.copySpace(2*curLevel)+"<"+curTag+getAttrs(attrs)+">";
for(int i=0;i<children.getLength();i++){
Node child=children.item(i);
curString +=getNodeString(child,curLevel);
}
//give the suffix
curString +="</"+curTag+">\n";
}
return curString;
}
}
现在唯一的问题是解析后的xml不能很好的缩进。 我在这个例子中给出了第二个方法。 以后逐步完善。
public static String getNodeString(Node node,int level);