一. 前言 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParser saxParser = saxParserFactory.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); SAXParseHandler saxParseHandler = new SAXParseHandler(); xmlReader.setContentHandler(saxParseHandler); InputStream is = getResources().openRawResource(R.raw.test); InputSource inputSource = new InputSource(is); xmlReader.parse(inputSource); saxParseHandler.getXmlList();
二. DefaultHandler重写方法的执行顺序 1. 继承 DefaultHandler 的类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 public class SAXParseHandler extends DefaultHandler { public static final String TAG = SAXParseHandler.class.getSimpleName(); private List<WebItem> webItems; private String ITEM = "item" ; private WebItem webItem; @Override public void startDocument () throws SAXException { super .startDocument(); Log.d(TAG,"startDocument" ); webItems = new ArrayList<>(); } @Override public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { super .startElement(uri, localName, qName, attributes); Log.d(TAG,"startElement localName:" +localName+" qName:" +qName); webItem = new WebItem(); if (TextUtils.equals(localName, ITEM)){ for (int i = 0 ; i < attributes.getLength(); i++) { if (TextUtils.equals(attributes.getLocalName(i),"id" )){ webItem.setId(Integer.parseInt(attributes.getValue(i))); } if (TextUtils.equals(attributes.getLocalName(i),"url" )){ webItem.setUrl(attributes.getValue(i)); } } } } @Override public void characters (char [] ch, int start, int length) throws SAXException { super .characters(ch, start, length); String content = String.valueOf(ch, start, length); Log.d(TAG,"characters ch:" +content); } @Override public void endElement (String uri, String localName, String qName) throws SAXException { super .endElement(uri, localName, qName); Log.d(TAG,"endElement localName:" +localName+" qName:" +qName); webItems.add(webItem); } @Override public void endDocument () throws SAXException { super .endDocument(); Log.d(TAG,"endDocument" ); } public List<WebItem> getXmlList () { return webItems; } }
2. 根据xml文件的内容将方法执行顺序输入到日志中 ① 只有一个根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="utf-8" ?> <web></web> startDocument startElement localName:web qName:web characters ch: characters ch: characters ch: endElement localName:web qName:web endDocument
② 根节点下有一个非根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0" encoding="utf-8" ?> <web> <item id="0" url="https://www.baidu.com">百度</item> </web> startDocument startElement localName:web qName:web characters ch: characters ch: startElement localName:item qName:item characters ch:百度 endElement localName:item qName:item characters ch: characters ch: characters ch: endElement localName:web qName:web endDocument
③ 根节点下有两个非根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?xml version="1.0" encoding="utf-8" ?> <web> <item id="0" url="https://www.baidu.com">百度</item> <item id="1" url="https://www.taobao.com">淘宝</item> </web> startDocument startElement localName:web qName:web characters ch: characters ch: startElement localName:item qName:item characters ch:百度 endElement localName:item qName:item characters ch: characters ch: startElement localName:item qName:item characters ch:淘宝 endElement localName:item qName:item characters ch: characters ch: characters ch: endElement localName:web qName:web endDocument
④ 根节点下有三个非根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?xml version="1.0" encoding="utf-8" ?> <web> <item id="0" url="https://www.baidu.com">百度</item> <item id="1" url="https://www.taobao.com">淘宝</item> <item id="2" url="https://www.qq.com">腾讯</item> </web> startDocument startElement localName:web qName:web characters ch: characters ch: startElement localName:item qName:item characters ch:百度 endElement localName:item qName:item characters ch: characters ch: startElement localName:item qName:item characters ch:淘宝 endElement localName:item qName:item characters ch: characters ch: startElement localName:item qName:item characters ch:腾讯 endElement localName:item qName:item characters ch: endElement localName:web qName:web endDocument
⑤ 根节点下有四个非根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <?xml version="1.0" encoding="utf-8" ?> <web> <item id="0" url="https://www.baidu.com">百度</item> <item id="1" url="https://www.taobao.com">淘宝</item> <item id="2" url="https://www.qq.com">腾讯</item> <item id="3" url="https://www.aili.com">阿里巴巴</item> </web> startDocument startElement localName:web qName:web characters ch: characters ch: startElement localName:item qName:item characters ch:百度 endElement localName:item qName:item characters ch: characters ch: startElement localName:item qName:item characters ch:淘宝 endElement localName:item qName:item characters ch: characters ch: startElement localName:item qName:item characters ch:腾讯 endElement localName:item qName:item characters ch: characters ch: startElement localName:item qName:item characters ch:阿里巴巴 endElement localName:item qName:item characters ch: endElement localName:web qName:web endDocument
⑥ 总结规律
如果是根节点,那么一定会执行以下的方法:
1 2 3 4 5 6 7 8 startDocument startElement localName:web qName:web characters ch: characters ch: characters ch: endElement localName:web qName:web endDocument
如果是非根节点,且根节点下的非根节点数 <= 两个,对于非根节点一定会执行以下的方法:
1 2 3 4 5 startElement localName:item qName:item characters ch:内容值 endElement localName:item qName:item characters ch: characters ch:
如果是非根节点,且根节点下的非根节点数 > 两个,对于非根节点一定会执行以下的方法:
1 2 3 4 5 6 7 8 9 10 11 startElement localName:item qName:item characters ch:内容值 endElement localName:item qName:item startElement localName:item qName:item characters ch:内容值 endElement localName:item qName:item characters ch: characters ch:
三. 实际小例子 1. 继承于DefaultHandler的SAXParseHandler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 public class SAXParseHandler extends DefaultHandler { public static final String TAG = SAXParseHandler.class.getSimpleName(); private List<WebItem> webItems; private String NODE_NAME = "item" ; private WebItem webItem; private String current_node_name; @Override public void startDocument () throws SAXException { super .startDocument(); Log.d(TAG,"startDocument" ); webItems = new ArrayList<>(); } @Override public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { super .startElement(uri, localName, qName, attributes); Log.d(TAG,"startElement localName:" +localName+" qName:" +qName); webItem = new WebItem(); if (TextUtils.equals(localName, NODE_NAME)){ current_node_name = localName; for (int i = 0 ; i < attributes.getLength(); i++) { if (TextUtils.equals(attributes.getLocalName(i),"id" )){ webItem.setId(Integer.parseInt(attributes.getValue(i))); } if (TextUtils.equals(attributes.getLocalName(i),"url" )){ webItem.setUrl(attributes.getValue(i)); } } } } @Override public void characters (char [] ch, int start, int length) throws SAXException { super .characters(ch, start, length); String content = String.valueOf(ch, start, length); Log.d(TAG,"characters ch:" +content); if (TextUtils.equals(current_node_name,NODE_NAME)){ webItem.setContent(content); } } @Override public void endElement (String uri, String localName, String qName) throws SAXException { super .endElement(uri, localName, qName); Log.d(TAG,"endElement localName:" +localName+" qName:" +qName); if (TextUtils.equals(current_node_name,NODE_NAME)){ webItems.add(webItem); } current_node_name = null ; } @Override public void endDocument () throws SAXException { super .endDocument(); Log.d(TAG,"endDocument" ); } public List<WebItem> getXmlList () { return webItems; } }
2. 待解析的Xml文件 1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="utf-8"?> <web > <item id ="0" url ="https://www.baidu.com" > 百度</item > <item id ="1" url ="https://www.taobao.com" > 淘宝</item > <item id ="2" url ="https://www.qq.com" > 腾讯</item > <item id ="3" url ="https://www.aili.com" > 阿里巴巴</item > <item id ="4" url ="https://www.taobao.com" > 淘宝</item > <item id ="5" url ="https://www.wechat.com" > 微信</item > <item id ="6" url ="https://www.timi.com" > 天美</item > <item id ="7" url ="https://www.guangzi.com" > 光子</item > <item id ="8" url ="https://www.taoken.com" > 字节跳动</item > <item id ="9" url ="https://www.douyin.com" > 抖音</item > </web >
3. Activity中的调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 public class MainActivity extends AppCompatActivity { @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { testSexParse(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void testSexParse () throws ParserConfigurationException, SAXException, IOException { XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); xmlReader.setContentHandler(new SAXParseHandler()); xmlReader.parse(new InputSource(getResources().openRawResource(R.raw.test))); SAXParseHandler saxParseHandler = (SAXParseHandler) xmlReader.getContentHandler(); for (WebItem webItem : saxParseHandler.getXmlList()) { addToRootLayout((LinearLayout) findViewById(R.id.root),webItem); } } private void addToRootLayout (LinearLayout layout, WebItem webItem) { View inflate = LayoutInflater.from(this ).inflate(R.layout.web_item_layout, null ); TextView id_text = inflate.findViewById(R.id.id); TextView content_text = inflate.findViewById(R.id.content); TextView url_text = inflate.findViewById(R.id.url); id_text.setText(String.valueOf(webItem.getId())); content_text.setText(webItem.getContent()); url_text.setText(webItem.getUrl()); layout.addView(inflate); } }
4. 运行结果
5. 源码地址 ParseXml
参考文章 sax中DefaultHander解析xml过程和先后顺序