上面的这条便签具有自我描述性。它拥有标题以及留言,同时包含了发送者和接受者的信息。但是,这个 XML 文档仍然没有做任何事情。它仅仅是包装在XML标签中的纯粹的信息。我们需要编写软件或者程序,才能传送、接收和显示出这个文档。 1.1.3 XML仅仅是纯文本 XML没什么特别的。它仅仅是纯文本而已。有能力处理纯文本的软件都可以处理XML。 不过,能够读懂 XML 的应用程序可以有针对性地处理 XML 的标签。标签的功能性意义依赖于应用程序的特性。 1.1.4 XML允许自定义标签 上例中的标签没有在任何XML标准中定义过(比如和)。这些标签是由文档的创作者发明的。这是因为XML没有预定义的标签。 在HTML中使用的标签(以及HTML的结构)是预定义的。HTML文档只使用在HTML标准中定义过的标签(比如<p>,<h1> 等等)。 XML允许创作者定义自己的标签和自己的文档结构。 1.1.5 XML不是对HTML的替代 XML是对HTML的补充。 XML不会替代HTML,理解这一点很重要。在大多数 web 应用程序中,XML用于传输数据,而HTML用于格式化并显示数据。 1.2 XML的语法 XML的语法规则很简单,且很有逻辑。这些规则很容易学习,也很容易使用。 1.2.1 所有元素都必须有关闭标签 在XML中,省略关闭标签是非法的。所有元素都必须有关闭标签。 在HTML,经常会看到没有关闭标签的元素: 复制代码 代码如下: <p>This is a paragraph <p>This is another paragraph
在XML中,省略关闭标签是非法的。所有元素都必须有关闭标签: 复制代码 代码如下: <p>This is a paragraph</p> <p>This is another paragraph</p>
父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞(兄弟或姐妹)。 所有元素均可拥有文本内容和属性(类似HTML中)。 1.6 XML DOM 想到这里,大家都有点迫不及待了,XML 文件到底如何解析呢? 但是,别急,让子弹先飞会儿:–) 在XML解析之前,我们必须系统性的学习一下 XML DOM 知识: 1.6.1 定义 XML DOM(XML Document Object Model) 定义了访问和操作XML文档的标准方法。 DOM把XML文档作为树结构来查看。能够通过DOM树来访问所有元素。可以修改或删除它们的内容,并创建新的元素。元素,它们的文本,以及它们的属性,都被认为是节点。 XML DOM是: 用于XML的标准对象模型 用于XML的标准编程接口 中立于平台和语言 W3C的标准 XML DOM定义了所有XML元素的对象和属性,以及访问它们的方法(接口)。 换句话说: XML DOM是用于获取、更改、添加或删除XML元素的标准 DOM将XML文档作为一个树形结构,而树叶被定义为节点。 1.6.2 总结 XML DOM其实比较复杂,在这么短的篇幅里也无法一一进行讲解。想详细了解XML DOM可以好好去学习下 1.7 XML如何解析? 上面讲了这么多关于XML的东西,那么XML文件应该如何解析呢? 终于到了我们的重头戏了 下面以视频项目为例,展示如何解析XML文件: 1.7.1 Step 1 XML文件是一棵树,首先需要找到对应的节点,然后从节点开始解析,比如搜索找到的就是result/weights/weight 和result/weights/weight 2个节点,分别从这个开始解析: 复制代码 代码如下: public ResultInfo onParser(Element rootElement) { int resp = -1; try { String elName = "header/respcode"; resp = Integer.parseInt(selectNodeString(rootElement, elName)); } catch (NumberFormatException e) { e.printStackTrace(); } Log.d(TAG, "resp= " + resp); if (resp != 0) { return null; } ResultInfo searchResultInfo = new ResultInfo(); // Parse Search Weight @SuppressWarnings("rawtypes") final List weights = rootElement.selectNodes(rootElement.getPath() + "/" + "result/weights/weight"); ResultInfo[] resultFilterInfos = parseVideos(weights); if (resultFilterInfos != null) { ResultInfo weight = new ResultInfo(); weight.putResultInfoArray(ResultInfo.KEY_VIDEOS, resultFilterInfos); searchResultInfo.putResultInfo(ResultInfo.KEY_WEIGHT, weight); } // Parse Albums @SuppressWarnings("rawtypes") final List albums = rootElement.selectNodes(rootElement.getPath() + "/" + "result/albums/album"); ResultInfo[] resultInfos = parseVideos(albums); if (resultInfos != null) { ResultInfo album = new ResultInfo(); album.putResultInfoArray(ResultInfo.KEY_VIDEOS, resultInfos); searchResultInfo.putResultInfo(ResultInfo.KEY_SEARCH, album); } return searchResultInfo; }
1.7.2 Step 2 找到了对应的Node,即从对应的Node开始递归的查找,直到找到最小的节点,也就是最基本的单元Element。再对每一个Element进行解析: 复制代码 代码如下: private ResultInfo[] parseVideos(final List nodes) { if (nodes != null && nodes.size() > 0) { final int size = nodes.size(); final ResultInfo[] vis = new ResultInfo[size]; int i = 0; for (Object o : nodes) { if (o instanceof Element) { final Element videoElement = (Element) o; ResultInfo vi = parseVideo(videoElement); vis[i] = vi; } i++; } return vis; } return null; }
1.7.3 Step 3 针对获取到的Element,解析出对应的String将数据传递给VideoInfo这个类: 复制代码 代码如下: private ResultInfo parseVideo(final Element videoElement) { final String id = videoElement.elementText("album_id"); final String title = videoElement.elementText("title"); final String categoryId = videoElement.elementText("category_id"); final String categoryName = videoElement.elementText("category_name"); final String count = videoElement.elementText("count"); final String imgUrl = videoElement.elementText("img180236"); final String duration = videoElement.elementText("duration"); final String mainactors = videoElement.elementText("mainactors"); final String sitename = videoElement.elementText("site_name"); final String videourl = videoElement.elementText("vedio_url"); final String sort = videoElement.elementText("sort"); final String tv_id = videoElement.elementText("tv_id"); ResultInfo vi = new ResultInfo(); vi.putString(VideoInfo.ID, id); vi.putString(VideoInfo.TITLE, title); vi.putString(VideoInfo.CATEGORY_ID, categoryId); vi.putString(VideoInfo.CATEGORY_NAME, categoryName); vi.putString(VideoInfo.COUNT, count); vi.putString(VideoInfo.IMG_URL, imgUrl); vi.putString(VideoInfo.DURATION, duration); vi.putString(VideoInfo.MAINACTORS, mainactors); vi.putString(VideoInfo.SITENAME, sitename); vi.putString(VideoInfo.VIDEOURL, videourl); vi.putString(VideoInfo.SORT, sort); vi.putString(VideoInfo.TV_ID, tv_id); return vi; }
1.7.4 Step 4 当使用XML解析器将XML数据解析出来之后。需要将这些数据提取出来,也是通过连续2层提取,将数据定位到每个video, 将每个video里的数据传递给SearchVideoInfo这个ArrayList,然后将ArrayList中的数据和对应的Adapter数据关联起来: 复制代码 代码如下: public static ArrayList<SearchVideoInfo> getSearchVideoInfo(ResultInfo searchResultInfo) { ResultInfo resultInfo = null; ResultInfo[] videos = null; ArrayList<SearchVideoInfo> searchVideoInfos = null; if (searchResultInfo != null) { resultInfo = searchResultInfo.getResultInfo(ResultInfo.KEY_SEARCH); } if (resultInfo != null) { videos = resultInfo.getResultInfoArray(ResultInfo.KEY_VIDEOS); } if (videos != null && videos.length > 0) { searchVideoInfos = new ArrayList<SearchVideoInfo>(videos.length); for (ResultInfo video : videos) { SearchVideoInfo searchInfo = new SearchVideoInfo(); searchInfo.setAlbum_id(video.getString(VideoInfo.ID)); searchInfo.setTitle(video.getString(VideoInfo.TITLE)); searchInfo.setChannel_id(video.getString(VideoInfo.CATEGORY_ID)); searchInfo.setImgUrl(video.getString(VideoInfo.IMG_URL)); searchInfo.setDuration(video.getString(VideoInfo.DURATION)); searchInfo.setMainActors(video.getString(VideoInfo.MAINACTORS)); searchInfo.setSiteName(video.getString(VideoInfo.SITENAME)); searchInfo.setVideo_url(video.getString(VideoInfo.VIDEOURL)); searchInfo.setOrder(video.getString(VideoInfo.SORT)); searchInfo.setTv_id(video.getString(VideoInfo.TV_ID)); // searchInfo.setContinueType(video.getString(VideoInfo.CONTINUETYPE)); searchVideoInfos.add(searchInfo); } } if (searchVideoInfos == null) { MyLog.e(TAG, "error, getSearchVideoInfo, can not get info"); } return searchVideoInfos; }