XML解析-SAX的使用

前端之家收集整理的这篇文章主要介绍了XML解析-SAX的使用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1.什么是SAX?

SAX,全称Simple API for XML,是一个用于处理XML事件驱动的“推”模型,虽然它不是W3C标准,但它却是一个得到了广泛认可的API。SAX解析器不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。

事件处理器类型:

  • 用于访问XML DTD内容的DTDHandler;
  • 用于低级访问解析错误的ErrorHandler;
  • 用于访问文档内容的ContentHandler,这也是最普遍使用的事件处理器。

优势

  • 提供对XML文档内容的有效低级访问;
  • 内存消耗小,因为整个文档无需一次加载到内存中;
  • 无需像在DOM中那样为所有节点创建对象;
  • 可用于广播环境,能够同时注册多个ContentHandler,并行接收事件。

劣势

  • 必须实现多个事件处理程序以便能够处理所有到来的事件;
  • 必须在应用程序代码中维护这个事件状态;
  • 不能支持随机访问。

2.使用的SAX类:

org.xml.sax:

  1. 有如下图:


org.xml.sax.ext:


org.xml.sax.helpers

3.实例

测试用的text.xml

  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <!-- <!DOCTYPE country SYSTEM "country.dtd"> -->
  3. <!DOCTYPE country [
  4. <!ELEMENT country (provinces?,states?,municipalites?)>
  5. <!ATTLIST country name CDATA #required>
  6. <!ELEMENT provinces (province+)>
  7. <!ELEMENT province (cities)>
  8. <!ATTLIST province name CDATA #required>
  9. <!ELEMENT cities (city+)>
  10. <!ELEMENT city (#PCDATA)>
  11. <!ATTLIST city name CDATA #required>
  12. ]>
  13. <country name="China">
  14. <provinces>
  15. <province name="GuangDong">
  16. <cities>
  17. <city name="GuangZhou">广州</city>
  18. <city name="ShenZhen">深圳</city>
  19. <city name="ZhuHai">珠海</city>
  20. </cities>
  21. </province>
  22. <province name="HuNan">
  23. <cities>
  24. <city name="ChangSha">长沙</city>
  25. <city name="HengYang">衡阳</city>
  26. <city name="ChangDe">常德</city>
  27. </cities>
  28. </province>
  29. </provinces>
  30. </country>

定义MyContentHandler类,实现ContentHandler接口:
  1. public static class MyContentHandler implements ContentHandler {
  2. private Locator locator;
  3. private int tentLength = 0;//此成员变量用于打印信息的缩进,以更好地观察输出内容
  4. @Override
  5. public void characters(char[] ch,int start,int length)
  6. throws SAXException {
  7. // TODO Auto-generated method stub
  8. //打印空格以缩进,下同
  9. for(int i =0;i<tentLength;i++){
  10. System.out.print(" ");
  11. }
  12. System.out.println("characters():\""+String.copyValueOf(ch,start,length)+"\"");
  13. }
  14.  
  15. @Override
  16. public void endDocument() throws SAXException {
  17. // TODO Auto-generated method stub
  18. for(int i =0;i<tentLength;i++){
  19. System.out.print(" ");
  20. }
  21. System.out.println("endDocument() called");
  22. }
  23.  
  24. @Override
  25. public void endElement(String uri,String localName,String qName)
  26. throws SAXException {
  27. // TODO Auto-generated method stub
  28. for(int i =0;i<tentLength;i++){
  29. System.out.print(" ");
  30. }
  31. System.out.println("endElement():</"+qName+">");
  32. }
  33.  
  34. @Override
  35. public void endPrefixMapping(String prefix) throws SAXException {
  36. // TODO Auto-generated method stub
  37. for(int i =0;i<tentLength;i++){
  38. System.out.print(" ");
  39. }
  40. System.out.println("endPrefixMapping():"+prefix);
  41. }
  42.  
  43. @Override
  44. public void ignorableWhitespace(char[] ch,int length)
  45. throws SAXException {
  46. // TODO Auto-generated method stub
  47. //System.out.println("ignorableWhitespace():"+length);
  48. tentLength = length;
  49. }
  50.  
  51. @Override
  52. public void processingInstruction(String target,String data)
  53. throws SAXException {
  54. // TODO Auto-generated method stub
  55. for(int i =0;i<tentLength;i++){
  56. System.out.print(" ");
  57. }
  58. System.out.println("processingInstruction():<"+target+","+data+">");
  59. }
  60.  
  61. @Override
  62. public void setDocumentLocator(Locator locator) {
  63. // TODO Auto-generated method stub
  64. this.locator = locator;
  65. for(int i =0;i<tentLength;i++){
  66. System.out.print(" ");
  67. }
  68. System.out.println("setDocumentLocator():["+locator+"]");
  69. }
  70.  
  71. @Override
  72. public void skippedEntity(String name) throws SAXException {
  73. // TODO Auto-generated method stub
  74. for(int i =0;i<tentLength;i++){
  75. System.out.print(" ");
  76. }
  77. System.out.println("skippedEntity():"+name);
  78. }
  79.  
  80. @Override
  81. public void startDocument() throws SAXException {
  82. // TODO Auto-generated method stub
  83. for(int i =0;i<tentLength;i++){
  84. System.out.print(" ");
  85. }
  86. System.out.println("startDocument() called");
  87. }
  88.  
  89. @Override
  90. public void startElement(String uri,String qName,Attributes atts) throws SAXException {
  91. // TODO Auto-generated method stub
  92. for(int i =0;i<tentLength;i++){
  93. System.out.print(" ");
  94. }
  95. System.out.println("startElement():<"+qName+">");
  96. }
  97.  
  98. @Override
  99. public void startPrefixMapping(String prefix,String uri)
  100. throws SAXException {
  101. // TODO Auto-generated method stub
  102. for(int i =0;i<tentLength;i++){
  103. System.out.print(" ");
  104. }
  105. System.out.println("startPrefixMapping():"+prefix);
  106. }
  107. }
首先,为了弄清楚这些方法调用顺序,我们在每个方法中将方法名和接收到的参数打印出来。以下是程序运行的main函数
  1. public static void main(String[] args) throws SAXException,IOException{
  2. File srcFile = new File("./test.xml");
  3. XMLReader xmlReader = XMLReaderFactory.createXMLReader();
  4. xmlReader.setFeature("http://xml.org/sax/features/validation",false);
  5. xmlReader.setContentHandler(new MyContentHandler());
  6. xmlReader.parse("./test.xml");
  7. }

输出结果:
  1. setDocumentLocator():[com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser$LocatorProxy@1a2961b]
  2. startDocument() called
  3. startElement():<country>
  4. startElement():<provinces>
  5. startElement():<province>
  6. startElement():<cities>
  7. startElement():<city>
  8. characters():"广州"
  9. endElement():</city>
  10. startElement():<city>
  11. characters():"深圳"
  12. endElement():</city>
  13. startElement():<city>
  14. characters():"珠海"
  15. endElement():</city>
  16. endElement():</cities>
  17. endElement():</province>
  18. startElement():<province>
  19. startElement():<cities>
  20. startElement():<city>
  21. characters():"长沙"
  22. endElement():</city>
  23. startElement():<city>
  24. characters():"衡阳"
  25. endElement():</city>
  26. startElement():<city>
  27. characters():"常德"
  28. endElement():</city>
  29. endElement():</cities>
  30. endElement():</province>
  31. endElement():</provinces>
  32. endElement():</country>
  33. endDocument() called

接下来,我们将该XML文件解析成一个Country 类对象。先定义两个类:
  1. public static class Province{
  2. public String name;
  3. public ArrayList<String> cities;
  4. public Province(){
  5. name = "";
  6. cities = new ArrayList<String>(5);
  7. }
  8. }
  9. public static class Country{
  10. public String name;
  11. public ArrayList<Province> provinces;
  12. public Country(){
  13. name = "";
  14. provinces = new ArrayList<Province>();
  15. }
  16. }
在MyContentHandler中声明如下成员变量:
  1. private Country country;
  2. private Province curProvince;
  3. private City curCity;
  4. private boolean isInCityElement = false;//指示当前事件处于City 元素中,用于获取城市的中文名称

由于该XML文件结构比较简单,我们只需要修改startElement()/character()/endElement()/endDocument()四个成员方法,如下:
  1. @Override
  2. public void characters(char[] ch,int length)
  3. throws SAXException {
  4. if(isInCityElement&&curCity != null){//若当前处于City元素中,则获取城市中文名称
  5. curCity.chName = String.copyValueOf(ch,length);
  6. }
  7. }
  8.  
  9. @Override
  10. public void endDocument() throws SAXException {
  11. //print Country object:将解析出来的Country类对象打印出来,验证解析是否正确
  12. System.out.println("country:"+country.name);
  13. int size = country.provinces.size();
  14. for(int i = 0;i<size;i++){
  15. Province prc = country.provinces.get(i);
  16. System.out.println(" |--"+prc.name);
  17. for(City city : prc.cities){
  18. System.out.println(" | |--"+city.enName+"("+city.chName+")");
  19. }
  20. }
  21. }
  22.  
  23. @Override
  24. public void endElement(String uri,String qName)
  25. throws SAXException {
  26. if(localName.equalsIgnoreCase("province")){
  27. if(curProvince != null){
  28. country.provinces.add(curProvince);
  29. curProvince = null;
  30. }
  31. }else if(localName.equalsIgnoreCase("city")){
  32. if(curProvince !=null&&curCity != null){
  33. curProvince.cities.add(curCity);
  34. curCity = null;
  35. }
  36. isInCityElement = false;//在此标记已不在City元素中
  37. }
  38. }
  39. @Override
  40. public void startElement(String uri,Attributes atts) throws SAXException {
  41. isInCityElement = true;
  42. if(localName.equalsIgnoreCase("country")){
  43. country = new Country();
  44. country.name = atts.getValue("name");
  45. }else if(localName.equalsIgnoreCase("province")){
  46. curProvince =new Province();
  47. curProvince.name = atts.getValue("name");
  48. }else if(localName.equalsIgnoreCase("city")){
  49. isInCityElement = true;//在此标记进入city元素中
  50. curCity = new City();
  51. curCity.enName = atts.getValue("name");
  52. }
  53. }
  1.  
输出结果:
  1. country:China
  2. |--GuangDong
  3. | |--GuangZhou(广州)
  4. | |--ShenZhen(深圳)
  5. | |--ZhuHai(珠海)
  6. |--HuNan
  7. | |--ChangSha(长沙)
  8. | |--HengYang(衡阳)
  9. | |--ChangDe(常德)

猜你在找的XML相关文章