JAVA與DOM解析器基礎 學習筆記

Cheng發表於2014-03-20

要求

    • 必備知識

      JAVA基礎知識。XML基礎知識。

    • 開發環境

      MyEclipse10

    • 資料下載

      原始碼下載

 

檔案物件模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴充套件置標語言的標準程式設計介面。各種語言可以按照DOM規範給出解析XML檔案的解析器。Sun公司釋出的JDK1.4的後續版本中提供瞭解析XML檔案的網API(Java API for XML Processing)。關於XML語法請參考這裡。為什麼沒有對java類和實際物件沒做詳細說明,我已經到程式碼中寫了註釋了,到這裡就不做過多的說明了。

檢測名稱空間:TestNameSpace.java

import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


/**
 * 檢查命xml標記的名稱空間
 * @author licheng
 *
 */
public class TestNameSpace {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SAXParserFactory factory=SAXParserFactory.newInstance(); //語法解析器的工廠物件
        factory.setNamespaceAware(true); //允許使用名稱空間
        try {
            SAXParser saxParser=factory.newSAXParser();  //獲取語法解析器
            MyHeader handle=new MyHeader(); //建立輸出控制程式碼
            saxParser.parse(new File("student.xml"), handle); //開始語法解析   檔案放到專案根目錄不是WebRoot
        }  catch (Exception e) {  //丟擲異常
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

/**
 * 建立輸出控制程式碼物件
 * @author Administrator
 *
 */
class MyHeader extends DefaultHandler{
    @Override //覆蓋父類的方法
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if(uri.length()>0) 
            System.out.println("標記:"+localName+"的名稱空間是:"+uri);
        else
            System.out.println("標記:"+localName+"沒有名稱空間");
    }
}

 

瀏覽器中的DOM解析器只檢測XML檔案是否是規範的,而不能檢測XML檔案的有效性,此時我們可以使用JAVA提供的DOM解析器來檢查一個XML檔案的有效性:

TestValidate.java

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

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

import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 檢查XML檔案的有效性
 * 瀏覽器中的XML解析器只檢查XML檔案是否是規範的,並不檢查XML檔案是否遵守DTD規定的約束條件。
 * 此時就可以使用DOM解析器來檢查一個XML檔案是否是有效的。
 * @author licheng
 *
 */
public class TestValidate {

    
    public static void main(String[] args) {
        String fileName=null;
        Scanner reader=new Scanner(System.in);  
        System.out.print("請輸入要驗證有效性的XML的檔案:");
        fileName=reader.nextLine();  //從控制檯讀取一行資料
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();  //DocumentBuilderFactory工廠物件 獲取自身例項 
        factory.setValidating(true);  //設定有效性檢測為真
        try {
            DocumentBuilder builer=factory.newDocumentBuilder();//獲取DOM解析器
            MyHandler handler=new MyHandler(); //建立MyHandler例項
            builer.setErrorHandler(handler); // 設定解析器的錯誤控制程式碼為 MyHandler的例項
            Document document=builer.parse(new File(fileName)); //DOM解析器解析 XML檔案
            if(handler.errorMessage==null){   //判斷handler物件是否含有錯誤資訊
                 System.out.print(fileName+"檔案是效的");
            }else{
                System.out.print(fileName+"檔案是無效的");
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}

/**
 * 建立輸出控制程式碼
 * @author Administrator
 *
 */
class MyHandler extends DefaultHandler{

    String errorMessage=null;
    /**
     * 一般性錯誤
     */
    public void error(SAXParseException e) throws SAXException {
        errorMessage=e.getMessage();
        System.out.print("一般錯誤:"+ errorMessage);
    }

    /*
     * 
     * 致命錯誤 程式終止
     */
    public void fatalError(SAXParseException e) throws SAXException {
        errorMessage=e.getMessage();
        System.out.print("致命錯誤:"+ errorMessage);
    }
    
    
}

 

獲取XML宣告資訊,根節點名稱,指定節點的資訊:JAXPOne.java

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.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


/**
 * JAVA DOM解析器入門   
 * 輸出書籍資訊
 * @author licheng
 *
 */
public class JAXPOne {

    
    public static void main(String[] args) {
        // DocumentBuilderFactory物件呼叫newInstance方法例項化一個DocumentBuilderFactory物件
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        try {
            //factory物件呼叫newDocumentBuilder建立 domParser DOM解析器
            DocumentBuilder domParser=factory.newDocumentBuilder();
            try {
                
                Document document=domParser.parse(new File("student.xml"));
                String version=document.getXmlVersion();  //獲取XML版本號
                System.out.println("version:"+version);
                
                String encoding=document.getXmlEncoding(); //獲取宣告編碼
                System.out.println("encoding:"+encoding);
                
                Element root=document.getDocumentElement(); //獲取根節點 是先要獲取根節點嗎
                String rootName=root.getNodeName(); //獲取節點的名稱
                System.out.println("rootName:"+rootName);
                System.out.println(rootName+"型別為:"+root.getNodeType()); //獲取節點型別 dom的級別
                
                NodeList nodelist=root.getElementsByTagName("book"); //獲取節點列表
                int size=nodelist.getLength();
                for(int k=0;k<size;k++){
                    Node node=nodelist.item(k); //獲取節點
                    String name=node.getNodeName(); //節點名稱
                    String content=node.getTextContent(); //獲取內容  包含子孫節點中的文字資料
                    System.out.println(name+":"+content);
                    //System.out.println(name+"節點型別:"+node.getNodeType()); //獲取節點型別 dom的級別
                }
                
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

 

使用遞迴方法輸出節點中的資料:JAXPTwo.java

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.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;


/**
 * 遞迴方法輸出節點中的資料
 * @author licheng
 *
 */
public class JAXPTwo {

    /**
     *主函式
     */
    public static void main(String[] args) {
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder domParser=factory.newDocumentBuilder();
        
            Document document=domParser.parse(new File("bookinfo.xml"));
            NodeList nodeList=document.getChildNodes();
            output(nodeList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        

    }
    
    
    /**
     * 遞迴輸出節點資料
     * @param nodelist 節點列表
     */
    public static  void output(NodeList nodelist){
        int size=nodelist.getLength();  //獲取接點列表的長度
        for(int k=0;k<size;k++){
            Node node=nodelist.item(k); //獲取節點列表中的一項 
            if(node.getNodeType()==node.TEXT_NODE){ //節點型別為TEXT
                Text textNode=(Text)node;
                String content=textNode.getWholeText();
                System.out.print(content);
            }
            if(node.getNodeType()==Node.ELEMENT_NODE){ //節點型別為ELEMENT
                Element elementNode=(Element)node;
                String name=elementNode.getNodeName();
                System.out.print(name);
                NodeList nodes=elementNode.getChildNodes();
                output(nodes);  //遞迴掉用該方法
            }
        }
        
    }

}

 

輸出Text節點資訊,統計一共有多少個Text文字節點:JAXPText.java

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.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;


/**
 * 統計一共有多少個Text節點
 * @author licheng
 *
 */
public class JAXPText {

    /**
     *主函式
     */
    public static void main(String[] args) {
        GiveData give=new GiveData();
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder domParser=factory.newDocumentBuilder();
            
            Document document=domParser.parse(new File("bookinfo.xml"));
            NodeList nodeList=document.getChildNodes();
            give.output(nodeList);
            System.out.println("一共有"+give.m+"個Text節點");
        } catch (Exception e) {
            e.printStackTrace();
        }
        

    }
    
}

class GiveData{
    int m=0; //text的個數
    public   void output(NodeList nodelist){
        int size=nodelist.getLength();  //獲取接點列表的長度
        for(int k=0;k<size;k++){
            Node node=nodelist.item(k); //獲取節點列表中的一項 
            if(node.getNodeType()==node.TEXT_NODE){ //節點型別為TEXT
                Text textNode=(Text)node;
                String content=textNode.getWholeText();
                m++;
                System.out.print(content);
            }
            if(node.getNodeType()==Node.ELEMENT_NODE){ //節點型別為ELEMENT
                Element elementNode=(Element)node;
                String name=elementNode.getNodeName();
                System.out.print(name);
                NodeList nodes=elementNode.getChildNodes();
                output(nodes);  //遞迴掉用該方法
            }
        }
        
    }
}

 

獲取Attr屬性節點資訊:JAXPAttr.java

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.Attr;
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;


/**
 * 遍歷屬性節點資訊
 * @author licheng
 *
 */
public class JAXPAttr {

    /**
     *主函式
     */
    public static void main(String[] args) {
        GiveData3 give=new GiveData3();
        
        try {
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            factory.setIgnoringElementContentWhitespace(true);  //忽略空白縮排
            DocumentBuilder domParser=factory.newDocumentBuilder();
            Document document=domParser.parse(new File("student.xml"));
            Element root=document.getDocumentElement();
            NodeList nodeList=root.getChildNodes();
            give.output(nodeList);
        
        } catch (Exception e) {
            e.printStackTrace();
        }
        

    }
    
}

class GiveData3{
    
    public   void output(NodeList nodelist){
        int size=nodelist.getLength();  //獲取接點列表的長度
        for(int k=0;k<size;k++){
            Node node=nodelist.item(k); //獲取節點列表中的一項 
            if(node.getNodeType()==node.TEXT_NODE){ //節點型別為TEXT
                Text textNode=(Text)node;
                String content=textNode.getWholeText();
                System.out.print(content);
            }
            if(node.getNodeType()==Node.ELEMENT_NODE){ //節點型別為ELEMENT
                Element elementNode=(Element)node;
                String name=elementNode.getNodeName();
                System.out.print(name);
                NamedNodeMap map=elementNode.getAttributes(); //獲取屬性節點集合
                /**
                 * 屬性節點操作
                 */
                for(int m=0;m<map.getLength();m++){
                    Attr attrNode=(Attr)map.item(m);
                    String attrName=attrNode.getName(); //屬性名稱
                    String attrValue=attrNode.getValue(); //屬性值
                    System.out.print(" "+attrName+"="+attrValue);
                }
                NodeList nodes=elementNode.getChildNodes();
                output(nodes);  //遞迴掉用該方法
            }
        }
        
    }
}

 

忽略文字空白:JAXPEight.java

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.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;




public class JAXPEight {


    public static void main(String[] args) {
        GiveD give=new GiveD();
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        factory.setIgnoringElementContentWhitespace(true); //這個確實是可行的嗎??
        try {
            DocumentBuilder domPaser=factory.newDocumentBuilder();
            Document document=domPaser.parse("student.xml");
            Element root=document.getDocumentElement();
            NodeList nodeList=root.getChildNodes();
            
            give.output(nodeList);
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}


class GiveD{
    int m=0;
    public void output(NodeList nodeList){
        int size=nodeList.getLength();
        for(int k=0;k<size;k++){
            Node node=nodeList.item(k);
            if(node.getNodeType()==Node.TEXT_NODE){
                Text textNode=(Text)node;
                String content=textNode.getWholeText();
                m++;
                System.out.print(content);
            }
            if(node.getNodeType()==Node.ELEMENT_NODE){
                Element elementNode=(Element)node;
                String name=elementNode.getNodeName();
                System.out.print(" ");
                NodeList nodes=elementNode.getChildNodes();
                output(nodes);
            }
        }
    }
    
}

 

[使用DOM生成XML檔案]此類通過已經存在的檔案 獲取Document物件 修改DOM後 建立XML檔案:JAXPTransformer.java

import java.io.File;
import java.io.FileOutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
 * 通過已經存在的檔案 獲取Document物件
 * 修改DOM後
 * DOM建立XML檔案
 * @author licheng
 *
 */
public class JAXPTransformer {
    public static void main(String[] args) {
        
        ModifyNode modify=new ModifyNode();
        try {
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            factory.setIgnoringElementContentWhitespace(true);  //忽略空白縮排
            DocumentBuilder domParser=factory.newDocumentBuilder();
            Document document=domParser.parse(new File("mobileNumber.xml")); //通過已經存在的檔案建立Document物件
            Element root=document.getDocumentElement();
            NodeList nodeList=root.getChildNodes();
            modify.modifyNode(nodeList, document); //呼叫修改DOM的方法
            TransformerFactory transFactory=TransformerFactory.newInstance(); //工廠物件獲取transFactory例項
            Transformer transformer=transFactory.newTransformer(); //獲取Transformer例項
            DOMSource domSource=new DOMSource(document);
            File file=new File("newXML.xml");
            FileOutputStream out=new FileOutputStream(file);
            StreamResult xmlResult=new StreamResult(out);
            transformer.transform(domSource, xmlResult);
        
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        

    }
}
class ModifyNode{
    int m=0;
    Document document;
    public  void modifyNode(NodeList nodeList,Document document){
        this.document=document;
        int size=nodeList.getLength();
        for(int k=0;k<size;k++){
            Node node=nodeList.item(k);
            if(node.getNodeType()==Node.ELEMENT_NODE){
                Element elementNode=(Element)node;  //這裡獲取節點
                String name=elementNode.getNodeName();//節點名稱
                if(name.equals("使用者")){ //節點判斷
                    m++;
                    Node textN=document.createTextNode("80元"); //建立文字節點
                    Node elementN=document.createElement("月租費"); //穿件節點
                    elementN.appendChild(textN);
                    elementNode.appendChild(elementN);
                }
                NodeList nodes=elementNode.getChildNodes();
                modifyNode(nodes, document); //此處遞迴
            }
        }
        
    }
    
    
    
    
    
    
    
}

[使用DOM生成XML檔案]上例中通過已有的XML檔案產生一個Document物件,而本例直接 呼叫 newDocument()方法獲取物件。

JAXPTransformer2.java

import java.io.File;
import java.io.FileOutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
 * domPaser 呼叫 newDocument() 方法獲取Document物件
 * 然後為Document節點新增子孫節點
 * 使用Transformer生成一個新的XML檔案
 * @author licheng
 *
 */
public class JAXPTransformer2 {
    public static void main(String[] args) {
        try {
            String[] personName={"張三","李四","王五"};
            String[] phoneNumber={"123","456","789"};
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            factory.setIgnoringElementContentWhitespace(true);  //忽略空白縮排
            DocumentBuilder domParser=factory.newDocumentBuilder();
            Document document=domParser.newDocument(); //通過呼叫newDocument() 方法獲取例項
            document.setXmlVersion("1.0"); //設定 xml版本號
            Element root=document.createElement("手機使用者表");
            document.appendChild(root); //新增根節點
            for(int k=1;k<=personName.length;k++){
                Node node=document.createElement("使用者"); //新增多個使用者節點
                root.appendChild(node);
            }
            NodeList nodeList=document.getElementsByTagName("使用者");
            int size=nodeList.getLength();
            for(int k=0;k<size;k++){
                Node node=nodeList.item(k);
                if(node.getNodeType()==Node.ELEMENT_NODE){ 
                    Element elementNode=(Element)node; //有必要建立此物件嗎???
                    Node nodeName=document.createElement("姓名");
                    Node nodeNumber=document.createElement("號碼");
                    nodeName.appendChild(document.createTextNode(personName[k]));
                    nodeNumber.appendChild(document.createTextNode(phoneNumber[k]));
                    elementNode.appendChild(nodeName);
                    elementNode.appendChild(nodeNumber);
                }
            }
            TransformerFactory transFactory=TransformerFactory.newInstance(); //工廠物件獲取transFactory例項
            Transformer transformer=transFactory.newTransformer(); //獲取Transformer例項
            DOMSource domSource=new DOMSource(document);
            File file=new File("phone.xml");
            FileOutputStream out=new FileOutputStream(file);
            StreamResult xmlResult=new StreamResult(out);
            transformer.transform(domSource, xmlResult);
            out.close();
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        

    }
}

 

作者:Li-Cheng
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

相關文章