1. Общ преглед
SAX, известен също като Simple API за XML , се използва за анализиране на XML документи.
В този урок ще научим какво е SAX и защо, кога и как трябва да се използва.
2. SAX : простият API за XML
SAX е API, използван за синтактичен анализ на XML документи. Той се основава на събития, генерирани по време на четене на документа. Методите за обратно извикване получават тези събития. Персонализиран манипулатор съдържа тези методи за обратно извикване.
Приложният програмен интерфейс (API) е ефективен, тъй като изпуска събитията веднага след получаването им. Следователно SAX има ефективно управление на паметта , за разлика от DOM например.
3. SAX срещу DOM
DOM означава Document Object Model. Най- синтактичен анализ на DOM не разчита на събития . Освен това зарежда целия XML документ в паметта, за да го анализира. SAX е по-ефективен от паметта от DOM.
DOM също има своите предимства. Например DOM поддържа XPath. Улеснява и работата с цялото дърво на документите наведнъж, тъй като документът се зарежда в паметта .
4. SAX срещу StAX
StAX е по-нова от SAX и DOM. Това означава Streaming API за XML .
Основната разлика с SAX е, че StAX използва механизъм за изтегляне вместо механизма за натискане на SAX (използвайки обратно извикване).
Това означава, че контролът се дава на клиента да реши кога трябва да се изтеглят събитията. Следователно няма задължение да се изтегли целият документ, ако е необходима само част от него.
Той осигурява лесен API за работа с XML с ефективен за памет начин за синтактичен анализ.
За разлика от SAX, той не предоставя проверка на схемата като една от характеристиките си.
5. Анализиране на XML файла с помощта на потребителски манипулатор
Нека сега използваме следния XML, представляващ уебсайта Baeldung и неговите статии:
Parsing an XML File Using SAX Parser SAX Parser's Lorem ipsum... Parsing an XML File Using DOM Parser DOM Parser's Lorem ipsum... Parsing an XML File Using StAX Parser StAX's Lorem ipsum...
Ще започнем, като създадем POJO за нашия корен елемент Baeldung и неговите деца:
public class Baeldung { private List articleList; // usual getters and setters }
public class BaeldungArticle { private String title; private String content; // usual getters and setters }
Ще продължим, като създадем BaeldungHandler . Този клас ще приложи методите за обратно извикване, необходими за улавяне на събитията.
Ще заменим четири метода от суперкласа DefaultHandler, всеки характеризиращ събитие:
-
- символи (char [], int, int) получава символи с граници. Ще ги преобразуваме в String и ще ги съхраним в променлива на BaeldungHandler
- startDocument () се извиква, когато синтактичният анализ започва - ще го използваме, за да изградим нашия екземпляр Baeldung
- startElement () се извиква, когато синтактичният анализ започва за елемент - ние ще го използваме за изграждане на екземпляри List или BaeldungArticle - qName ни помага да правим разлика между двата типа
- endElement () се извиква, когато разборът завършва за елемент - това е моментът, когато ще присвоим съдържанието на маркерите на съответните им променливи
С всички дефинирани обратно извиквания вече можем да напишем класа BaeldungHandler :
public class BaeldungHandler extends DefaultHandler { private static final String ARTICLES = "articles"; private static final String ARTICLE = "article"; private static final String TITLE = "title"; private static final String CONTENT = "content"; private Baeldung website; private String elementValue; @Override public void characters(char[] ch, int start, int length) throws SAXException { elementValue = new String(ch, start, length); } @Override public void startDocument() throws SAXException { website = new Baeldung(); } @Override public void startElement(String uri, String lName, String qName, Attributes attr) throws SAXException { switch (qName) { case ARTICLES: website.articleList = new ArrayList(); break; case ARTICLE: website.articleList.add(new BaeldungArticle()); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { switch (qName) { case TITLE: latestArticle().title = elementValue; break; case CONTENT: latestArticle().content = elementValue; break; } } private BaeldungArticle latestArticle() { List articleList = website.articleList; int latestArticleIndex = articleList.size() - 1; return articleList.get(latestArticleIndex); } public Baeldung getWebsite() { return website; } }
Добавени са и константи на низа, за да се увеличи четливостта. Методът за извличане на последната срещана статия също е удобен. И накрая, имаме нужда от гетер за обекта Baeldung .
Обърнете внимание, че горното не е безопасно за нишки, тъй като ние държим на състояние между извикванията на метода.
6. Тестване на анализатора
За да тестваме парсера, ще създадем екземпляр на SaxFactory , SaxParser, а също и BaeldungHandler :
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); SaxParserMain.BaeldungHandler baeldungHandler = new SaxParserMain.BaeldungHandler();
След това ще анализираме XML файла и ще твърдим, че обектът съдържа всички очаквани анализирани елементи:
saxParser.parse("src/test/resources/sax/baeldung.xml", baeldungHandler); SaxParserMain.Baeldung result = baeldungHandler.getWebsite(); assertNotNull(result); List articles = result.getArticleList(); assertNotNull(articles); assertEquals(3, articles.size()); SaxParserMain.BaeldungArticle articleOne = articles.get(0); assertEquals("Parsing an XML File Using SAX Parser", articleOne.getTitle()); assertEquals("SAX Parser's Lorem ipsum...", articleOne.getContent()); SaxParserMain.BaeldungArticle articleTwo = articles.get(1); assertEquals("Parsing an XML File Using DOM Parser", articleTwo.getTitle()); assertEquals("DOM Parser's Lorem ipsum...", articleTwo.getContent()); SaxParserMain.BaeldungArticle articleThree = articles.get(2); assertEquals("Parsing an XML File Using StAX Parser", articleThree.getTitle()); assertEquals("StAX Parser's Lorem ipsum...", articleThree.getContent());
Както се очакваше, баелунгът е анализиран правилно и съдържа очакваните под-обекти.
7. Заключение
Току-що открихме как да използваме SAX за синтактичен анализ на XML файлове. Това е мощен API, генериращ лек отпечатък от паметта в нашите приложения.
Както обикновено, кодът за тази статия е достъпен в GitHub.