(Extensible Markup Language (XML) 1.0 (Fifth Edition))
XML 파서의 종류는 SAX 파서와 DOM 파서가 있다.
SAX 파서와 DOM 파서의 차이점:
참고 - http://www.ibiblio.org/xml/books/xmljava/chapters/ch09s11.html
(Choosing between SAX and DOM)
> 요약: 어떤 파서를 사용할지는 아래와 같은 상황을 고려하여 선택하는 편이 좋다.
SAX 파서를 사용하는 상황
- 파싱하려는 XML 크기가 너무 클 때
- 파싱하려는 XML 중 필요한 정보만 취합하고자 할 때
- 실시간으로 파싱을 처리하고자 할때
DOM 파서를 사용하는 상황
- XML 문서안에 넓게 분포된 자료들 한번에 취합하고자 할 때
- 파싱하려는 XML 문서 구조가 매우 복잡할 때
- XML 문서를 수정할 때
- 파싱한 XML 정보를 여러 함수들이 사용하고자 할 때
파서 사용법:
예) RSS 파일을 파싱하는 예
NY times 사이트의 RSS 링크 중 하나를 선택하여 nyfeed.xml 이라는 파일명으로 저장하였다.
RSS 항목들 중 item 항목에 대한 title 과 link 만 추려서 출력한다.
프로젝트 구조는 아래와 같다.
실행 결과는 아래와 같다.
nyfeed.xml
XMLParseTest.java
같은 일을 하는 함수 두개를 만들었다. domParseTest() 와 saxParseTest() 함수이다.
1. nyfeed.xml 파일을 읽어 파싱한다.
2. item 항목의 title 과 link 내용을 출력한다.
팁)
SAX 파싱 작업 중 더 이상 작업 할 필요가 없을 때는 SAXException 을 날려서 중단하면 된다.
참고 - http://www.ibm.com/developerworks/xml/library/x-tipsaxstop/
예) RSS 파일을 파싱하는 예
NY times 사이트의 RSS 링크 중 하나를 선택하여 nyfeed.xml 이라는 파일명으로 저장하였다.
RSS 항목들 중 item 항목에 대한 title 과 link 만 추려서 출력한다.
프로젝트 구조는 아래와 같다.
실행 결과는 아래와 같다.
DOM 파서
SAX 파서
nyfeed.xml
아래 링크로 접속하여 소스 보기 한 후 내용을 복사하여 프로젝트 폴더에 nyfeed.xml 파일로 저장
http://feeds.nytimes.com/nyt/rss/World
XMLParseTest.java
같은 일을 하는 함수 두개를 만들었다. domParseTest() 와 saxParseTest() 함수이다.
1. nyfeed.xml 파일을 읽어 파싱한다.
2. item 항목의 title 과 link 내용을 출력한다.
package xml.parse; import java.io.File; import javax.xml.parsers.*; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * XMLParserTest */ public class XMLParserTest { private final String XML_FILE_PATH = "nyfeed.xml"; /** * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { XMLParserTest xpt = new XMLParserTest(); xpt.domParseTest(); xpt.saxParseTest(); } /** * * @throws Exception */ public void domParseTest() throws Exception { System.out.println("=============================="); System.out.println("domParseTest()"); System.out.println("=============================="); File xmlFile = new File(XML_FILE_PATH); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(xmlFile); doc.getDocumentElement().normalize(); System.out.printf("Root element:%s\n", doc.getDocumentElement().getNodeName()); NodeList itemNodeList = doc.getElementsByTagName("item"); for (int s = 0; s < itemNodeList.getLength(); s++) { Node itemNode = itemNodeList.item(s); if (itemNode.getNodeType() == Node.ELEMENT_NODE) { Element itemElement = (Element)itemNode; NodeList titleNodeList = itemElement.getElementsByTagName("title"); Element titleElement = (Element)titleNodeList.item(0); NodeList childTitleNodeList = titleElement.getChildNodes(); System.out.printf("[title : %s]\n", ((Node)childTitleNodeList.item(0)).getNodeValue()); NodeList linkNodeList = itemElement.getElementsByTagName("link"); Element linkElement = (Element) linkNodeList.item(0); NodeList childLinkNodeList = linkElement.getChildNodes(); System.out.printf("[link : %s]\n", ((Node)childLinkNodeList.item(0)).getNodeValue()); } } } /** * * @throws Exception */ public void saxParseTest() throws Exception { System.out.println("=============================="); System.out.println("saxParseTest()"); System.out.println("=============================="); File xmlFile = new File(XML_FILE_PATH); SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); DefaultHandler dh = new DefaultHandler() { private boolean firstElement = true; private boolean inItem = false; private boolean inTitle = false; private boolean inLink = false; private StringBuilder characterSB; @Override public void startDocument() throws SAXException { System.out.println("startDocument"); super.startDocument(); } @Override public void endDocument() throws SAXException { System.out.println("endDocument"); super.endDocument(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (firstElement) { System.out.printf("Root element:%s\n", qName); firstElement = false; } if (qName.equals("item")) { inItem = true; } else if (qName.equals("title")) { inTitle = true; } else if (qName.equals("link")) { inLink = true; } if (inItem && (inTitle || inLink)) { characterSB = new StringBuilder(); } super.startElement(uri, localName, qName, attributes); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (characterSB != null) { characterSB.append(handleCharacters(ch, start, length)); } super.characters(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (characterSB != null) { if (inItem && inTitle) { System.out.printf("[title : %s]\n", characterSB.toString()); } else if (inItem && inLink) { System.out.printf("[link : %s]\n", characterSB.toString()); } characterSB = null; } if (qName.equals("item")) { inItem = false; } else if (qName.equals("title")) { inTitle = false; } else if (qName.equals("link")) { inLink = false; } super.endElement(uri, localName, qName); } /** * * @param ch * @param start * @param end * @return */ public String handleCharacters(char[] ch, int start, int length) { StringBuilder sb = new StringBuilder(); for (int i = start; i < start + length; i++) { sb.append(ch[i]); } return sb.toString(); } }; parser.parse(xmlFile, dh); } }
팁)
SAX 파싱 작업 중 더 이상 작업 할 필요가 없을 때는 SAXException 을 날려서 중단하면 된다.
참고 - http://www.ibm.com/developerworks/xml/library/x-tipsaxstop/
(Tip: Stop a SAX parser when you have enough data)
throw new SAXException("Enough!");