ANDROID: парсинг XML - PullRequest
       17

ANDROID: парсинг XML

4 голосов
/ 01 октября 2010

Я не разработчик, я просто увлекаюсь программированием. Одна область, которую я никогда не понимаю, это синтаксический анализ XML. К сожалению, для моего последнего «проекта» мне нужно сделать именно это для приложения для Android. Это прототип, который я делаю для работы.

У меня есть этот XML (файл макета):

<feed version="201010011221" > 
  <period from="2010-10-01T10:08:34Z" to="2010-10-01T10:08:34Z"> 
    <lines> 
      <line id="SKI" name="Ski" shortname="ski" status="1 calls queued"> 
        <calls> 
          <call id="6584" created="2010-10-01T11:22:42Z">
            <booking>1275243</booking>
          </call> 
        </calls> 
      </line> 
      <line id="CRU" name="Cruise" shortname="cruise" status="0 calls queued"> 
        <calls /> 
      </line> 
      <line id="VIL" name="Villas" shortname="villas" status="2 calls queued"> 
        <calls> 
          <call id="25878" created="2010-10-01T10:22:42Z">
            <booking>1077244</booking>
          </call> 
          <call id="25878" created="2010-10-01T10:22:42Z">
            <booking>1077244</booking>
          </call> 
        </calls> 
      </line>
    </lines>
  </period> 
</feed>

У меня есть код, который возвращает мне NodeList каждого из них:

inputStream = OpenHttpConnection(URL);
Document document = null;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder;
documentBuilder = documentBuilderFactory.newDocumentBuilder();
document = documentBuilder.parse(inputStream);
document.getDocumentElement().normalize();
NodeList lineNodes = document.getElementsByTagName("line");

Я не уверен, что делать дальше. Мой код кажется довольно длинным для этого. Я гуглил лучшие методы, но нашел более чистый код и не смог приступить к работе.

Есть ли какие-нибудь хорошие учебники по Android XML? Или может кто-нибудь помочь мне с этим кодом?

Мне нужно поместить каждый в HashMap, где String является идентификатором.

Строка - это класс всей отображаемой информации.

Спасибо Neil

1 Ответ

7 голосов
/ 01 октября 2010

Я бы предпочел не использовать DOM, так как он занимает больше места в памяти. С DOM вся структура XML сначала загружается в память, а затем обрабатывается. Возможно, это не лучшее решение для мобильной разработки.

Используйте SAX-парсер, который поставляется с Android. Это событийный подход. Каждый начальный тег, содержимое между тегами и конечный тег запускают события, когда они происходят. На самом деле он может обрабатывать больше событий, но это наиболее часто используемые события. Это означает, что синтаксический анализатор SAX обрабатывает каждую строку одну за другой без предварительной загрузки всей структуры XML в память.

Я опубликую пример вашей конкретной проблемы завтра.

РЕДАКТИРОВАТЬ: Вот пример обещанного обработчика контента.

import java.util.HashMap;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

public class MyContentHandler implements ContentHandler {

    private HashMap<String, Object> feed;
    private HashMap<String, Object> peroidContent;
    private HashMap<String, Object> callContent;
    private HashMap<String, Object> callsMap;
    private HashMap<String, Object> lineContent;
    private HashMap<String, Object> linesMap;

    private String text;
    private String callId;
    private String lineId;

    @Override
    public void startDocument() throws SAXException {
        /* You can perform some action in this method
         * for example to reset some sort of Collection
         * or any other variable you want. It gets called
         * every time a document starts. */
        feed = new HashMap<String, Object>();
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        // Gets called every time an opening tag is encountered.
        if(localName.equalsIgnoreCase("FEED")) {
            /* We've found a "feed" opening tag so we capture its
             * version attribute and put it into our HashMap.*/
            feed.put("Version", atts.getValue("version"));
        } else if(localName.equalsIgnoreCase("PEROID")) {
            peroidContent = new HashMap<String, Object>();
            peroidContent.put("From", atts.getValue("from"));
            peroidContent.put("to", atts.getValue("to"));
        } else if(localName.equalsIgnoreCase("LINE")) {
            linesMap = new HashMap<String, Object>();
        } else if(localName.equalsIgnoreCase("LINE")) {
            lineContent = new HashMap<String, Object>();
            lineId = atts.getValue("id");
            lineContent.put("name", atts.getValue("name"));
            lineContent.put("shortname", atts.getValue("shortname"));
            lineContent.put("status", atts.getValue("status"));
        } else if(localName.equalsIgnoreCase("CALLS")) {
            callsMap = new HashMap<String, Object>();
        } else if(localName.equalsIgnoreCase("CALL")) {
            callContent = new HashMap<String, Object>();
            callId = atts.getValue("Id");
            callContent.put("created", atts.getValue("created"));
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        /* Gets called every time in between an opening tag and
         * a closing tag if characters are encountered. */
        text = new String(ch, start, length);
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // Gets called every time a closing tag is encountered.
        if(localName.equalsIgnoreCase("FEED")) {
            feed.put("Peroid", peroidContent);
        } else if(localName.equalsIgnoreCase("PEROID")) {
            peroidContent.put("Lines", linesMap);
        } else if(localName.equalsIgnoreCase("LINES")) {
            linesMap.put(lineId, lineContent);
        } else if(localName.equalsIgnoreCase("LINE")) {
            lineContent.put("Calls", callsMap);
        } else if(localName.equalsIgnoreCase("CALLS")) {
            callsMap.put(callId, callContent);
        } else if(localName.equalsIgnoreCase("BOOKING")) {
            callContent.put("Booking", text.toString());
        }
    }

    @Override
    public void endDocument() throws SAXException {
        /* You can perform some action in this method
         * for example to reset some sort of Collection
         * or any other variable you want. It gets called
         * every time a document end is reached. */
        SAXParsingFun.setHashMap(feed);
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException {
        // TODO Auto-generated method stub
    }

    @Override
    public void ignorableWhitespace(char[] ch, int start, int length)
            throws SAXException {
        // TODO Auto-generated method stub
    }

    @Override
    public void processingInstruction(String target, String data)
            throws SAXException {
        // TODO Auto-generated method stub
    }

    @Override
    public void setDocumentLocator(Locator locator) {
        // TODO Auto-generated method stub
    }

    @Override
    public void skippedEntity(String name) throws SAXException {
        // TODO Auto-generated method stub
    }

    @Override
    public void startPrefixMapping(String prefix, String uri)
            throws SAXException {
        // TODO Auto-generated method stub
    }
}

В StackOverflow много объяснений о том, как анализировать XML-файл, я оставил это и только показал вам более интересную часть; обработчик содержимого.

Теперь большинство интересных частей прокомментированы, чтобы вы могли понять, что я пытаюсь сделать.

Я реализовал интерфейс ContentHandler только для того, чтобы показать вам, что доступно больше методов, возможно, вам понадобится один из них в будущем. Однако вместо этого вы можете расширить класс DefaultHandler и просто перезаписать необходимые методы. Все, что вы делаете, это в основном проверяете наличие определенных тегов и затем запускаете определенные события. Если вы хотите сохранить порядок элементов в файле XML, вы просто используете LinkedHashMap вместо HashMap.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...