Java StAX 解析器 - 解析 XML 文件



Java StAX 解析器 API 包含用於以事件形式解析 XML 文件的類、方法和介面。它是一個基於拉取的 API,使客戶端程式能夠僅在需要時訪問事件,從而擁有更多許可權。在本章中,我們將詳細瞭解如何使用 StAX 解析器 API 在 Java 中解析 XML 文件。

使用 Java StAX 解析器解析 XML

以下是使用 Java StAX 解析器解析文件時使用的步驟:

  • 步驟 1:建立 XMLInputFactory 例項
  • 步驟 2:讀取 XML
  • 步驟 3:解析 XML
  • 步驟 4:檢索元素

步驟 1:建立 XMLInputFactory 例項

XMLInputFactory 類是一個抽象類,用於獲取輸入流。要建立 XMLInputFactory 的新例項,我們使用 newInstance() 方法。如果無法載入此工廠的例項,則會丟擲一個名為“FactoryConfigurationError”的錯誤。

XMLInputFactory factory = XMLInputFactory.newInstance();

步驟 2:讀取 XML

FileReader 類用於從輸入檔案讀取字元流。如果找不到檔案或由於某些原因無法讀取檔案,則以下語句將丟擲“FileNotFoundException”。

FileReader fileReader = new FileReader("src/input.txt");

除了從檔案讀取 XML 內容外,我們還可以獲取字串形式的內容並將其轉換為位元組,如下所示:

StringBuilder xmlBuilder = new StringBuilder();
xmlBuilder.append("<class>xyz</class>");
ByteArrayInputStream input = new ByteArrayInputStream(xmlBuilder.toString().getBytes("UTF-8"));

步驟 3:解析 XML

要解析 XML 事件,我們透過傳遞 FileReader 物件或輸入流物件從 XMLInputFactory 物件建立 XMLEventReader。如果 XMLEventReader 的建立不成功,則會丟擲 XMLStreamException。

XMLEventReader eventReader = factory.createXMLEventReader(input);

步驟 4:檢索元素

XMLEventReader 的nextEvent() 方法以 XMLEvent 物件的形式返回下一個 XML 事件。XMLEvent 具有將事件作為 startElement、endElement 和 Characters 返回的方法。

XMLEvent event = eventReader.nextEvent();

檢索元素名稱

要檢索元素名稱,我們應該首先從 XML 文件中獲取元素。當事件型別為 XMLStreamConstants.START_ELEMENT 時,XMLEvent 物件上的asStartElement() 會以 StartElement 物件的形式檢索元素。

StartElement 的getName() 方法以字串形式返回元素的名稱。

示例

RetrieveElementName.java 程式將 StringBuilder 物件中的 XML 內容獲取並轉換為位元組。獲得的 InputStream 用於建立 XMLEventReader。元素是使用解析器通知的事件訪問的。

import java.io.ByteArrayInputStream;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

public class RetrieveElementName {
   public static void main(String args[]) {
      try {
    	  
         //Creating XMLInputFactory instance
    	 XMLInputFactory factory = XMLInputFactory.newInstance();
    	  
    	 //Reading the XML
 	     StringBuilder xmlBuilder = new StringBuilder();
 	     xmlBuilder.append("<class>xyz</class>");
 	     ByteArrayInputStream input = new ByteArrayInputStream(xmlBuilder.toString().getBytes("UTF-8"));
 	     
 	     //Parsing the XML
         XMLEventReader eventReader =
         factory.createXMLEventReader(input);
         
         //Retrieving the Elements
         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            if(event.getEventType()==XMLStreamConstants.START_ELEMENT) {
            StartElement startElement = event.asStartElement();
            System.out.println("Element Name: " + startElement.getName());
            }
         }  
      } catch(Exception e) {
    	  e.printStackTrace();
      }
   }
}

輸出

元素的名稱顯示在輸出螢幕上。

Element Name: class

檢索文字內容

要檢索元素的文字內容,在 XMLEvent 物件上使用asCharacters() 方法。只有當事件型別為 XMLStreamConstants.CHARACTERS 時,我們才能使用 asCharacters() 方法。此方法以 Characters 物件的形式返回資料。getData() 方法用於以字串形式獲取文字內容。

示例

在前面的示例中,我們將 XML 內容作為輸入流獲取。現在,讓我們透過將以下 XML 內容儲存在名為“classData.xml”的檔案中來讀取檔案作為輸入。

<class>xyz</class>

在以下RetrievingTextContent.java 程式中,我們使用 FileReader 物件讀取了 classData.xml 檔案,並將其作為輸入傳遞給 XMLEventReader。使用 XMLEvent 物件,我們獲得了元素的文字內容。

import java.io.FileReader;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;

public class RetrievingTextContent {
   public static void main(String args[]) {
      try {
    	  
    	 //Creating XMLInputFactory instance
    	 XMLInputFactory factory = XMLInputFactory.newInstance();
    	 
    	 //Reading the XML
    	 FileReader fileReader = new FileReader("classData.xml");
    	 
    	 //Parsing the XML
         XMLEventReader eventReader =
         factory.createXMLEventReader(fileReader);
         
         //Retrieving the Elements
         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            if(event.getEventType()==XMLStreamConstants.CHARACTERS) {
            	Characters characters = event.asCharacters();
            	System.out.println("Text Content : "+ characters.getData());
            }
         }  
      } catch(Exception e) {
    	  e.printStackTrace();
      }
   }
}

輸出

元素的文字內容顯示在輸出螢幕上。

Text Content : xyz

檢索屬性

StartElement 介面的getAttributes() 方法返回在此元素上宣告的屬性的只讀迭代器。如果在此元素上沒有宣告任何屬性,則返回一個空迭代器。

Attribute 介面上的getValue() 函式以字串形式返回屬性的值。

示例

以下classData.xml 包含三個學生的資訊以及他們的學號作為屬性。讓我們使用 Java 中的 StAX API 檢索此資訊。

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>

在以下RetrieveAttributes.java 程式中,我們使用了 switch case 語句來處理 START_ELEMENT、CHARACTERS 和 END_ELEMENT XMLStreamConstants,以訪問所有元素的資訊。

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Iterator;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

public class RetrievingAttributes {
   public static void main(String[] args) {
      boolean bFirstName = false;
      boolean bLastName = false;
      boolean bNickName = false;
      boolean bMarks = false;
      
      try {
    	  
         //Creating XMLInputFactory instance 
         XMLInputFactory factory = XMLInputFactory.newInstance(); 
         
         //Reading the XML
         FileReader fileReader = new FileReader("classData.xml");
         
         //Parsing the XML
         XMLEventReader eventReader =
         factory.createXMLEventReader(fileReader);
         
         //Retrieving the Elements
         while(eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
              
            switch(event.getEventType()) {
               
               case XMLStreamConstants.START_ELEMENT:
                  StartElement startElement = event.asStartElement();
                  String qName = startElement.getName().getLocalPart();

               if (qName.equalsIgnoreCase("student")) {
                  System.out.println("Start Element : student");
                  Iterator<Attribute> attributes = startElement.getAttributes();
                  String rollNo = attributes.next().getValue();
                  System.out.println("Roll No : " + rollNo);
               } else if (qName.equalsIgnoreCase("firstname")) {
                  bFirstName = true;
               } else if (qName.equalsIgnoreCase("lastname")) {
                  bLastName = true;
               } else if (qName.equalsIgnoreCase("nickname")) {
                  bNickName = true;
               }
               else if (qName.equalsIgnoreCase("marks")) {
                  bMarks = true;
               }
               break;

               case XMLStreamConstants.CHARACTERS:
                  Characters characters = event.asCharacters();
               if(bFirstName) {
                  System.out.println("First Name: " + characters.getData());
                  bFirstName = false;
               }
               if(bLastName) {
                  System.out.println("Last Name: " + characters.getData());
                  bLastName = false;
               }
               if(bNickName) {
                  System.out.println("Nick Name: " + characters.getData());
                  bNickName = false;
               }
               if(bMarks) {
                  System.out.println("Marks: " + characters.getData());
                  bMarks = false;
               }
               break;

               case XMLStreamConstants.END_ELEMENT:
                  EndElement endElement = event.asEndElement();
                  
               if(endElement.getName().getLocalPart().equalsIgnoreCase("student")) {
                  System.out.println("End Element : student");
                  System.out.println();
               }
               break;
            } 
         }
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (XMLStreamException e) {
         e.printStackTrace();
      }
   }
}

輸出

所有學生的資訊以及他們的學號都顯示在輸出螢幕上。

Start Element : student
Roll No : 393
First Name: dinkar
Last Name: kad
Nick Name: dinkar
Marks: 85
End Element : student

Start Element : student
Roll No : 493
First Name: Vaneet
Last Name: Gupta
Nick Name: vinni
Marks: 95
End Element : student

Start Element : student
Roll No : 593
First Name: jasvir
Last Name: singn
Nick Name: jazz
Marks: 90
End Element : student
廣告