2010-10-01 186 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