西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)其它知識 → 使用XML 就應(yīng)該簡單點(diǎn)

使用XML 就應(yīng)該簡單點(diǎn)

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:本站整理時間:2011/3/13 21:07:44字體大。A-A+

作者:佚名點(diǎn)擊:66次評論:0次標(biāo)簽: XML

  • 類型:下載工具大。828KB語言:中文 評分:7.5
  • 標(biāo)簽:
立即下載

對于現(xiàn)在越來越輕量級,越來越講究速度和接近用戶的應(yīng)用來說,xml確實(shí)有點(diǎn)復(fù)雜了。解析起來不僅耗內(nèi)存,而且很復(fù)雜。這就好像花了幾千塊錢買了個MS Office,但是80%的feature都用不著,還白白的耗著CPU和內(nèi)存。

個人覺得,設(shè)置文件用XML其實(shí)挺好,因?yàn)樵O(shè)置文件一般并不太大,而且要求可讀性強(qiáng),還有很多亂七八糟的需求,可以利用XML的力量。昨天搞chrome的設(shè)置,發(fā)現(xiàn)chrome的設(shè)置文件也是使用的json,讀起來也是輕松愉快。

前陣子做了個程序,需要解析豆瓣API調(diào)用返回的XML。真想說一句。。。豆瓣你別用XML了。。。至少,提供個json版的API調(diào)用吧。

(以上謹(jǐn)代表個人觀點(diǎn))

===================正文=================

解析豆瓣返回的xml,實(shí)在是不想用DOM這個重量級的玩意。DOM這個玩意,說它強(qiáng)大好還是說它官僚好呢。我傾向于使用SAXP解析。但是現(xiàn)在面臨的一個問題是,我需要根據(jù)xml節(jié)點(diǎn)的名字和屬性值(一個或者多個)來決定當(dāng)前的值是不是我想要的。這就麻煩一點(diǎn)點(diǎn)。第一反應(yīng)是考慮xpath。后來覺得不如自己做一個得了,權(quán)當(dāng)是按需定制一個輕量級的xpath。

首先定義XMLSearchUnit類,這個類的實(shí)例用來描述一個需要在XML中搜索的值,值可以是xml節(jié)點(diǎn)的值,或者是節(jié)點(diǎn)的屬性。

package com.deepnighttwo.resourceresolver.douban.resolver.utils;

import java.util.HashMap;
import java.util.Map;

import org.xml.sax.Attributes;

/**
*
* Represent a search task. Target could be value of a node or attribute of the
* node.
*
*
@author mzang
*/
publicclass XMLSearchUnit {

// attribute values to be matched during search
private Map<String, String> attributeMatchValidation =new HashMap<String, String>();

// if target is an attribute, then set this member to be the attribute name.
// if it is null or empty, then means the target is node value.
private String expectedAttr;

// xml path, format is: /node_name/node_name/...
private String xmlPath;

public XMLSearchUnit(String xmlPath) {
this.xmlPath = xmlPath;
}

/**
* if current node meets the search conditions or not. Meets means the path
* is correct and the attribute value is matched.
*
*
@param path
*
@param attributes
*
@return
*/
publicboolean match(String path, Attributes attributes) {
if (xmlPath.equals(path) ==false) {
returnfalse;
}

for (String key : attributeMatchValidation.keySet()) {
String exp
= attributeMatchValidation.get(key);
String compare
= attributes.getValue(key);
if (exp.equalsIgnoreCase(compare) ==false) {
returnfalse;
}
}
returntrue;
}

public Map<String, String> getAttributeMatchValidation() {
return attributeMatchValidation;
}

publicvoid addAttributeValidation(String key, String value) {
attributeMatchValidation.put(key, value);
}

public String getXmlPath() {
return xmlPath;
}

publicvoid setAttributeMatchValidation(
Map
<String, String> attributeMatchValidation) {
this.attributeMatchValidation = attributeMatchValidation;
}

public String getExpectedAttr() {
return expectedAttr;
}

/**
* if target is node value, then set expectedAttr to null. if target is an
* attribute value, set it to be the attribute name.
*
*
@param expectedAttr
*/
publicvoid setExpectedAttr(String expectedAttr) {
this.expectedAttr = expectedAttr;
}

/**
* hash code can be cached if all properties are not be be changed.
*/
@Override
publicint hashCode() {
finalint prime =31;
int result =1;
result
= prime
* result
+ ((attributeMatchValidation ==null) ?0
: attributeMatchValidation.hashCode());
result
= prime * result
+ ((expectedAttr ==null) ?0 : expectedAttr.hashCode());
result
= prime * result + ((xmlPath ==null) ?0 : xmlPath.hashCode());
return result;
}

@Override
publicboolean equals(Object obj) {
if (this== obj)
returntrue;
if (obj ==null)
returnfalse;
if (getClass() != obj.getClass())
returnfalse;
XMLSearchUnit other
= (XMLSearchUnit) obj;
if (attributeMatchValidation ==null) {
if (other.attributeMatchValidation !=null)
returnfalse;
}
elseif (!attributeMatchValidation
.equals(other.attributeMatchValidation))
returnfalse;
if (expectedAttr ==null) {
if (other.expectedAttr !=null)
returnfalse;
}
elseif (!expectedAttr.equals(other.expectedAttr))
returnfalse;
if (xmlPath ==null) {
if (other.xmlPath !=null)
returnfalse;
}
elseif (!xmlPath.equals(other.xmlPath))
returnfalse;
returntrue;
}

}

這個類比較簡單。就是用一個hashmap保待匹配的attribut鍵值對,用一個字符串表示期待的attribute name,用一個字符串表示期待的node path。

然后就是如何在SAXP里用到這個類的實(shí)例去搜索了。

package com.deepnighttwo.resourceresolver.douban.resolver.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
*
* SAXP parser working with XMLSearchUnit.
*
*
@author mzang
*/

publicclass DoubanSearchParser extends DefaultHandler {

// create and initial search units
publicstaticfinal XMLSearchUnit DETAILS_LINK_API_PATH =new XMLSearchUnit(
"/feed/entry/id");

publicstaticfinal XMLSearchUnit DETAILS_CONTENT_PATH =new XMLSearchUnit(
"/entry/summary");

publicstaticfinal XMLSearchUnit DETAILS_TITLE_PATH =new XMLSearchUnit(
"/entry/title");

publicstaticfinal XMLSearchUnit DETAILS_CHINESE_NAME_PATH =new XMLSearchUnit(
"/entry/db:attribute");

publicstaticfinal XMLSearchUnit DETAILS_RATINGE_PATH =new XMLSearchUnit(
"/entry/gd:rating");

publicstaticfinal XMLSearchUnit DETAILS_RATINGE_RATER_COUNT_PATH =new XMLSearchUnit(
"/entry/gd:rating");

publicstaticfinal XMLSearchUnit DETAILS_LINK_URL_PATH =new XMLSearchUnit(
"/feed/entry/link");

static {
DETAILS_LINK_URL_PATH.addAttributeValidation(
"rel", "alternate");
DETAILS_LINK_URL_PATH.setExpectedAttr(
"href");

DETAILS_CHINESE_NAME_PATH.addAttributeValidation(
"lang", "zh_CN");
DETAILS_CHINESE_NAME_PATH.addAttributeValidation(
"name", "aka");

DETAILS_RATINGE_PATH.setExpectedAttr(
"average");

DETAILS_RATINGE_RATER_COUNT_PATH.setExpectedAttr(
"numRaters");

}

// a map to store the XMLSearchUnit and value
private Map<XMLSearchUnit, String> results =new HashMap<XMLSearchUnit, String>();

// a counter of search unit. if it is 0, then all search unit finds a match
// value and the result of the XML will be skipped.
privateint count =0;

private StringBuilder path =new StringBuilder();

privatestaticfinal String pathSeparater ="/";

private XMLSearchUnit[] searchUnits;

List
<XMLSearchUnit> foundItems =new ArrayList<XMLSearchUnit>();

/**
* constructor, accept XML input stream, 0 or more search unit instances.
*
*
@param input
*
@param expectedPath
*
@return
*/
public Map<XMLSearchUnit, String> parseResults(InputStream input,
XMLSearchUnit... expectedPath) {
for (XMLSearchUnit search : expectedPath) {
results.put(search,
null);
}

searchUnits
= expectedPath;

count
= expectedPath.length;

XMLReader xmlReader
=null;
try {
SAXParserFactory spfactory
= SAXParserFactory.newInstance();
spfactory.setValidating(
false);
SAXParser saxParser
= spfactory.newSAXParser();
xmlReader
= saxParser.getXMLReader();
xmlReader.setContentHandler(
this);
xmlReader.parse(
new InputSource(input));
}
catch (Exception e) {
System.err.println(e);
System.exit(
1);
}
return results;
}

privatevoid addToPath(String addPath) {
path.append(pathSeparater).append(addPath.toLowerCase());
}

privatevoid popPath() {
int index = path.lastIndexOf(pathSeparater);
// String removedPath = path.substring(index);
path.delete(index, path.length());
}

@Override
publicvoid startElement(String uri, String localName, String qName,
Attributes attributes)
throws SAXException {
foundItems.clear();
if (count ==0) {
return;
}

// update path
addToPath(qName);

List
<XMLSearchUnit> foundAttrItems =null;

// check if current node matches search units. if it is a node value
// search, then store it in a member variable named foundItems because
// the value of the node is known only when reaches the end of the
// node.but for attribute search, it value is known here. So then are
// put in a local variable list named foundAttrItems.
for (XMLSearchUnit unit : searchUnits) {
if (unit.match(path.toString(), attributes) ==true) {

if (unit.getExpectedAttr() ==null) {
foundItems.add(unit);
}
else {
if (foundAttrItems ==null) {
foundAttrItems
=new ArrayList<XMLSearchUnit>();
}
foundAttrItems.add(unit);
}
}
}
// if no attribute match, return.
if (foundAttrItems ==null) {
return;
}

// fill search unit value using attribute value. update count.
for (XMLSearchUnit attrUnit : foundAttrItems) {
String attrValue
= attributes.getValue(attrUnit.getExpectedAttr());
if (results.get(attrUnit) ==null) {
count
--;
}
results.put(attrUnit, attrValue);
count
--;
}
}

/**
* if current node matches, the the node value is useful, store it.
*/
@Override
publicvoid characters(char[] ch, int start, int length)
throws SAXException {
if (count ==0) {
return;
}
if (foundItems.size() ==0) {
return;
}

for (XMLSearchUnit unit : foundItems) {
String content
=new String(ch, start, length);
if (results.get(unit) ==null) {
count
--;
}
results.put(unit, content);
}
}

@Override
publicvoid endElement(String uri, String localName, String qName)
throws SAXException {
foundItems.clear();
if (count ==0) {
return;
}
popPath();
}
}

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)