Java&Xml教程(五)使用SAX方式解析XML文件

互联网 17-2-22

javax.xml.parsers.SAXParser类提供了一些函数,采用事件处理方式解析XML文档,这个类实现了XMLReader接口,提供了重载的parse()方法从File,InputStream,SAX InputSource和URI字符串中读取XML文档。 实际的XML解析工作由Handler类来完成,我们需要创建自己的Handler类,这就需要我们实现org.xml.sax.ContentHandler接口。这个接口中包含当事件发生时接收通知的回调方法,例如 StartDocument, EndDocument, StartElement, EndElement, CharacterData等等。

org.xml.sax.helpers.DefaultHandler提供了ContentHandler接口的默认实现,因此我们可以继承该类实现自己的处理类。继承这个类是明智的选择,因为我们可能只需要实现一些方法。继承这个类可以保证代码的简洁和可维护性。 下面是我们要解析的XML文档: employees.xml

<?xml version="1.0" encoding="UTF-8"?><Employees>      <Employee id="1">          <age>29</age>          <name>Pankaj</name>          <gender>Male</gender>          <role>Java Developer</role>      </Employee>      <Employee id="2">          <age>35</age>          <name>Lisa</name>          <gender>Female</gender>          <role>CEO</role>      </Employee>      <Employee id="3">          <age>40</age>          <name>Tom</name>          <gender>Male</gender>          <role>Manager</role>      </Employee>      <Employee id="4">          <age>25</age>          <name>Meghna</name>          <gender>Female</gender>          <role>Manager</role>      </Employee></Employees>

该XML文件内容存放一些员工的信息,每个员工包含id属性和age, name, gender,role字段。 我们將使用SAX解析机制处理XML文件并创建员工对象列表。 我们使用Employee类抽象员工的信息:Employee.java

package com.journaldev.xml;public class Employee {      private int id;          private String name;          private String gender;          private int age;          private String role;          public int getId() {              return id;      }    public void setId(int id) {              this.id = id;      }    public String getName() {              return name;      }    public void setName(String name) {              this.name = name;      }    public String getGender() {              return gender;      }    public void setGender(String gender) {              this.gender = gender;      }    public int getAge() {              return age;      }    public void setAge(int age) {              this.age = age;      }    public String getRole() {              return role;      }    public void setRole(String role) {              this.role = role;      }    @Override      public String toString() {              return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +                      " Role=" + this.role;      }    }

接着继承DefaultHandler类创建自己的Handler类MyHandler.java

package com.journaldev.xml.sax;  import java.util.ArrayList;  import java.util.List;  import org.xml.sax.Attributes;  import org.xml.sax.SAXException;  import org.xml.sax.helpers.DefaultHandler;  import com.journaldev.xml.Employee;  public class MyHandler extends DefaultHandler {        //List to hold Employees object      private List<Employee> empList = null;          private Employee emp = null;          //getter method for employee list      public List<Employee> getEmpList() {              return empList;      }          boolean bAge = false;          boolean bName = false;          boolean bGender = false;          boolean bRole = false;          @Override      public void startElement(String uri, String localName, String qName, Attributes attributes)                  throws SAXException {              if (qName.equalsIgnoreCase("Employee")) {                  //create a new Employee and put it in Map              String id = attributes.getValue("id");                          //initialize Employee object and set id attribute              emp = new Employee();              emp.setId(Integer.parseInt(id));                          //initialize list              if (empList == null)                  empList = new ArrayList<>();          } else if (qName.equalsIgnoreCase("name")) {                      //set boolean values for fields, will be used in setting Employee variables              bName = true;          } else if (qName.equalsIgnoreCase("age")) {              bAge = true;          } else if (qName.equalsIgnoreCase("gender")) {              bGender = true;          } else if (qName.equalsIgnoreCase("role")) {              bRole = true;          }      }    @Override      public void endElement(String uri, String localName, String qName) throws SAXException {              if (qName.equalsIgnoreCase("Employee")) {                  //add Employee object to list              empList.add(emp);          }      }    @Override      public void characters(char ch[], int start, int length) throws SAXException {              if (bAge) {                  //age element, set Employee age              emp.setAge(Integer.parseInt(new String(ch, start, length)));              bAge = false;          } else if (bName) {              emp.setName(new String(ch, start, length));              bName = false;          } else if (bRole) {              emp.setRole(new String(ch, start, length));              bRole = false;          } else if (bGender) {              emp.setGender(new String(ch, start, length));              bGender = false;          }      }  }

MyHandler类持有一个存放Employee对象的List引用,它只有一个对应的getter方法。Employee对象在事件处理函数中被添加到List对象,在MyHandler类中还定义了Employee对象和它的几个字段相关的boolean类型变量用于创建Employee对象,当Employee对象的所有属性都被设置时,它就会被添加到list中。 我们重写了几个重要的方法startElement(), endElement() 和characters(). 当SAXParser 开始解析文档时遇到元素的开始标签时,startElement() 方法就会被调用,我们重写了这个方法,使用boolean类型变量来区分元素类别。我们也是在该方法中,当Employee 标签开始时创建Employee 对象。 当SAXParser遇到元素中的字符串数据时characters()方法会被调用,我们使用boolean类型字段为Employee对象的属性进行赋值。 endElement()方法则会在SAXParser 遇到XML结束标签时会被调用,在这里我们將Employee对象添加到List对象中。 在下面的测试程序中,我们使用MyHandler解析XML文档生成存放Employee 对象List。 XMLParserSAX.java

package com.journaldev.xml.sax;  import java.io.File;  import java.io.IOException;  import java.util.List;  import javax.xml.parsers.ParserConfigurationException;  import javax.xml.parsers.SAXParser;  import javax.xml.parsers.SAXParserFactory;  import org.xml.sax.SAXException;  import com.journaldev.xml.Employee;  public class XMLParserSAX {        public static void main(String[] args) {      SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();      try {          SAXParser saxParser = saxParserFactory.newSAXParser();          MyHandler handler = new MyHandler();          saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);          //Get Employees list          List<Employee> empList = handler.getEmpList();          //print employee information          for(Employee emp : empList)              System.out.println(emp);      } catch (ParserConfigurationException | SAXException | IOException e) {          e.printStackTrace();      }      }    }

运行程序输出:

Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java DeveloperEmployee:: ID=2 Name=Lisa Age=35   Gender=Female Role=CEOEmployee:: ID=3 Name=Tom Age=40   Gender=Male Role=ManagerEmployee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager

Java SAX解析机制为我们提供了一系列的API来处理XML文件,SAX解析和DOM解析方式不太一样,它并不是將XML文件内容一次性全部加载,而是连续的部分加载。

javax.xml.parsers.SAXParser类提供了一些函数,采用事件处理方式解析XML文档,这个类实现了XMLReader接口,提供了重载的parse()方法从File,InputStream,SAX InputSource和URI字符串中读取XML文档。 实际的XML解析工作由Handler类来完成,我们需要创建自己的Handler类,这就需要我们实现org.xml.sax.ContentHandler接口。这个接口中包含当事件发生时接收通知的回调方法,例如 StartDocument, EndDocument, StartElement, EndElement, CharacterData等等。

org.xml.sax.helpers.DefaultHandler提供了ContentHandler接口的默认实现,因此我们可以继承该类实现自己的处理类。继承这个类是明智的选择,因为我们可能只需要实现一些方法。继承这个类可以保证代码的简洁和可维护性。 下面是我们要解析的XML文档: employees.xml

<?xml version="1.0" encoding="UTF-8"?><Employees>      <Employee id="1">          <age>29</age>          <name>Pankaj</name>          <gender>Male</gender>          <role>Java Developer</role>      </Employee>      <Employee id="2">          <age>35</age>          <name>Lisa</name>          <gender>Female</gender>          <role>CEO</role>      </Employee>      <Employee id="3">          <age>40</age>          <name>Tom</name>          <gender>Male</gender>          <role>Manager</role>      </Employee>      <Employee id="4">          <age>25</age>          <name>Meghna</name>          <gender>Female</gender>          <role>Manager</role>      </Employee></Employees>

该XML文件内容存放一些员工的信息,每个员工包含id属性和age, name, gender,role字段。 我们將使用SAX解析机制处理XML文件并创建员工对象列表。 我们使用Employee类抽象员工的信息:Employee.java

package com.journaldev.xml;public class Employee {      private int id;          private String name;          private String gender;          private int age;          private String role;          public int getId() {              return id;      }    public void setId(int id) {              this.id = id;      }    public String getName() {              return name;      }    public void setName(String name) {              this.name = name;      }    public String getGender() {              return gender;      }    public void setGender(String gender) {              this.gender = gender;      }    public int getAge() {              return age;      }    public void setAge(int age) {              this.age = age;      }    public String getRole() {              return role;      }    public void setRole(String role) {              this.role = role;      }    @Override      public String toString() {              return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +                      " Role=" + this.role;      }    }

接着继承DefaultHandler类创建自己的Handler类MyHandler.java

package com.journaldev.xml.sax;  import java.util.ArrayList;  import java.util.List;  import org.xml.sax.Attributes;  import org.xml.sax.SAXException;  import org.xml.sax.helpers.DefaultHandler;  import com.journaldev.xml.Employee;  public class MyHandler extends DefaultHandler {        //List to hold Employees object      private List<Employee> empList = null;          private Employee emp = null;          //getter method for employee list      public List<Employee> getEmpList() {              return empList;      }          boolean bAge = false;          boolean bName = false;          boolean bGender = false;          boolean bRole = false;          @Override      public void startElement(String uri, String localName, String qName, Attributes attributes)                  throws SAXException {              if (qName.equalsIgnoreCase("Employee")) {                  //create a new Employee and put it in Map              String id = attributes.getValue("id");                          //initialize Employee object and set id attribute              emp = new Employee();              emp.setId(Integer.parseInt(id));                          //initialize list              if (empList == null)                  empList = new ArrayList<>();          } else if (qName.equalsIgnoreCase("name")) {                      //set boolean values for fields, will be used in setting Employee variables              bName = true;          } else if (qName.equalsIgnoreCase("age")) {              bAge = true;          } else if (qName.equalsIgnoreCase("gender")) {              bGender = true;          } else if (qName.equalsIgnoreCase("role")) {              bRole = true;          }      }    @Override      public void endElement(String uri, String localName, String qName) throws SAXException {              if (qName.equalsIgnoreCase("Employee")) {                  //add Employee object to list              empList.add(emp);          }      }    @Override      public void characters(char ch[], int start, int length) throws SAXException {              if (bAge) {                  //age element, set Employee age              emp.setAge(Integer.parseInt(new String(ch, start, length)));              bAge = false;          } else if (bName) {              emp.setName(new String(ch, start, length));              bName = false;          } else if (bRole) {              emp.setRole(new String(ch, start, length));              bRole = false;          } else if (bGender) {              emp.setGender(new String(ch, start, length));              bGender = false;          }      }  }

MyHandler类持有一个存放Employee对象的List引用,它只有一个对应的getter方法。Employee对象在事件处理函数中被添加到List对象,在MyHandler类中还定义了Employee对象和它的几个字段相关的boolean类型变量用于创建Employee对象,当Employee对象的所有属性都被设置时,它就会被添加到list中。 我们重写了几个重要的方法startElement(), endElement() 和characters(). 当SAXParser 开始解析文档时遇到元素的开始标签时,startElement() 方法就会被调用,我们重写了这个方法,使用boolean类型变量来区分元素类别。我们也是在该方法中,当Employee 标签开始时创建Employee 对象。 当SAXParser遇到元素中的字符串数据时characters()方法会被调用,我们使用boolean类型字段为Employee对象的属性进行赋值。 endElement()方法则会在SAXParser 遇到XML结束标签时会被调用,在这里我们將Employee对象添加到List对象中。 在下面的测试程序中,我们使用MyHandler解析XML文档生成存放Employee 对象List。 XMLParserSAX.java

package com.journaldev.xml.sax;  import java.io.File;  import java.io.IOException;  import java.util.List;  import javax.xml.parsers.ParserConfigurationException;  import javax.xml.parsers.SAXParser;  import javax.xml.parsers.SAXParserFactory;  import org.xml.sax.SAXException;  import com.journaldev.xml.Employee;  public class XMLParserSAX {        public static void main(String[] args) {      SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();      try {          SAXParser saxParser = saxParserFactory.newSAXParser();          MyHandler handler = new MyHandler();          saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);          //Get Employees list          List<Employee> empList = handler.getEmpList();          //print employee information          for(Employee emp : empList)              System.out.println(emp);      } catch (ParserConfigurationException | SAXException | IOException e) {          e.printStackTrace();      }      }    }

运行程序输出:

Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java   DeveloperEmployee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEOEmployee:: ID=3 Name=Tom Age=40   Gender=Male Role=ManagerEmployee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager

以上就是Java&Xml教程(五)使用SAX方式解析XML文件的内容,更多相关内容请关注PHP中文网(www.php.cn)!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:Java&Xml教程(四)使用DOM方式生成XML文件

相关资讯