2010-10-01 238 views
4

我不是開發人員,我只是涉足編程。我從來不懂的一個領域是XML解析。可悲的是,對於我最新的「項目」,我需要爲android應用程序做這件事情。它是我爲工作而做的原型。ANDROID:解析XML

我有這樣的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是ID。

線是顯示的所有信息的類。

感謝 尼爾

+0

http://stackoverflow.com/questions/4827344/how-to-parse-xml-using-the-sax-parser – hakre 2014-10-21 19:42:41

回答

7

我ñ寧可不使用DOM,因爲它有一個更大的內存佔用。使用DOM時,首先將整個XML結構加載到內存中,然後處理它。這可能不是移動開發的最佳解決方案。

使用Android自帶的SAX解析器。這是一種事件驅動的方法。每個起始標籤,標籤之間的內容以及發生時結束標籤觸發事件。事實上它可以處理更多的事件,但這些是最常用的事件。這意味着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 
    } 
} 

有很多關於如何解析XML文件,在計算器上的解釋我已經離開了這一點,只是顯示你的更有趣的部分;內容處理程序。

現在大多數有趣的部分都有評論,所以你可以理解我正在嘗試做什麼。

我已經實現了接口ContentHandler只是爲了向您說明有更多的方法可用,也許您將來需要其中的一種方法。但是,您可以從類DefaultHandler延伸,只需覆蓋所需的方法。你所做的只是檢查某些標籤的發生,然後觸發某些事件。如果要保留XML文件中元素的順序,則只需使用LinkedHashMap而不是HashMap

我希望它有幫助。

+0

感謝您的例子...看起來不錯,我想我正在理解它。 Eclipse不喜歡SAXParsingFun.setHashMap(feed);我想這不是SAX的一部分,但不清楚如何解決... – neildeadman 2010-10-04 13:13:19

+1

哦,抱歉,這是我的錯。它是我用來初始化解析過程的另一個類的一部分。這只是將HashMap發送給其他類的一種方式。我實際上只解釋了ContentHandler是如何工作的。 – 2010-10-04 13:27:47

+0

我想知道我是否可以就此提出進一步的問題?我非常喜歡你介紹給我的方法,它似乎運作良好。但是,在我之後 ...標籤我有另一個標籤,我覺得不需要提及。這是。如果什麼都沒有,我會得到。然而,無論什麼值,只要它到達這些標籤,我的代碼就會失敗。 Eclipse打開另一個選項卡:「ExpatParser.startElement(String,String,String,int,int)line:50」&「Source not found」。我無法找到拋出任何異常的地方......你能幫忙嗎? – neildeadman 2010-10-05 14:02:38