这篇文章主要介绍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);