zyl910

优化技巧、硬件体系、图像处理、图形学、游戏编程、国际化与文本信息处理。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

3.1 纯JavaScript转换xml

 

  因为xml对命名空间的规定比较严格,就算是同一套命名空间的不同版本,也会报告命名空间冲突。按照这个规定,我们必须为每一个版本写一套xsl转换,这样做太麻烦了。而且有可能Google又会更新xml名称空间的版本,那时我们的xsl又会不兼容了。

  这时还不如放弃xsl,用JavaScript分析xml的数据,并将其加工为html字符串。这样就能绕过命名空间问题。

  而且JavaScript下,我们能更灵活的处理数据,比如解决绝对地址问题。

 

  纯JavaScript转换xml其实并不复杂,基本上只需要改动showxml函数——

// 显示xml
function showxml(urlPath, divdoc, xmlDoc)
{
if (null==divdoc) return;
if (null==xmlDoc)
{
divdoc.innerHTML = "error!";
return;
}
// == main ==
//divdoc.innerHTML = xml_transformNode(xmlDoc, xsl);
//divdoc.innerHTML = "OK!";
// Parse
var sall = ""; // 所有内容
var nodes=xmlDoc.documentElement.childNodes;
for(var i=0; i<nodes.length; i++) // 第一级。sdk:platform, sdk:sample, ...
{
var nod = nodes[i];
var stag = nod.nodeName.substr(4); // 标签名
if (1==nod.nodeType) // 节点类型为元素时
{
var nod2 = nod.selectSingleNode("sdk:archives"); // 第二级。sdk:archives(文件集)
if (null!=nod2) // 当文件集存在时才添加
{
// 读取参数
var sapilevel = xml_text(nod.selectSingleNode("sdk:api-level"));
var srevision = xml_text(nod.selectSingleNode("sdk:revision"));
var sdescription = xml_text(nod.selectSingleNode("sdk:description"));
// 标题
var stitle = stag + "(";
if (""!=sapilevel) stitle += sapilevel + ", ";
stitle += "r" + srevision + "): " + sdescription;
// 添加
sall += "<h2>" + stitle + "</h2>\n";
// 档案
for(var i3=0; i3<nod2.childNodes.length; i3++) // 第三级。sdk:archive
{
var nod3 = nod2.childNodes[i3];
if ("sdk:archive"==nod3.nodeName)
{
var surl = xml_text(nod3.selectSingleNode("sdk:url"));// 下载地址
if (null!=surl)
{
if (surl.indexOf("//")<0) surl = urlPath + surl; // 将相对路径转为绝对路径
// 添加url
//sall += "" + surl + "<br/>\n"; // 文本模式
sall += "<a href='" + surl + "'>" + surl + "</a><br/>\n"; // 链接模式
}
}
}
}
}
}
divdoc.innerHTML = sall;
}


 

  重点改动——

1.多了一个urlPath参数,用于传递路径。

2.判断是相对地址,还是绝对地址——“if (surl.indexOf("//")<0) surl = urlPath + surl”。

3.将下载地址以链接的方式显示,便于用下载工具下载——“sall += "<a href='" + surl + "'>" + surl + "</a><br/>\n"”

 

 

3.2 计算路径

 

  为什么要加一个urlPath参数呢?这时因为其他厂家的SDK没有放在“https://dl-ssl.google.com/android/repository/”上,而是在厂商自己的网站上。在doload函数中需计算好路径,再传递给showxml函数——

// 加载xml
function doload(url, desc)
{
// 创建边框div
var divrect = document.createElement("div");
divrect.className = "div_border";
divrect.title = url;
divrect.innerHTML = "<input type='button' value='-' onclick='click_show(this)'>" +
"&nbsp;" + url + "<br />" +
((""!=desc)?("<b>desc</b>: " + desc + "<br />"):"")+
"<div name='divdoc'>loading...</div>";

// add
var divShow = getRef("divShow");
divShow.appendChild(divrect);
divShow.appendChild(document.createElement("br")); // 空一行

// 计算路径
var urlPath = "http://dl.google.com/android/repository/"; // 默认路径
if (url.indexOf("//")>=0)
{
// 是外网路径,进行转换
urlPath = url.substr(0, url.lastIndexOf("/")+1);
}

// 加载xml
xml_loadFile(url, function(xmlDoc, isError){
// 用xsl转换xml
var divdoc = divrect.lastChild;
showxml(urlPath, divdoc, isError?null:xmlDoc);
});
}


 

 

3.3 全部代码

 

  全部代码为——

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Anroid SDK URL 3</title>
<style type="text/css">
.div_border
{
border
:red dotted thin;
padding
: 2px;
}
</style>
<script type="text/javascript" src="zyllibjs_xml.js"></script>
<script type="text/javascript">
// 取得命名对象
function getRef(id)
{
if (document.getElementById) return document.getElementById(id); // DOM
if (document.all) return document.all[id]; // IE4
if (document.layers) return document.layers[id]; // Netscape4
returnnull;
}

// 显示或隐藏控件
function setShow(ctl, isShow, _display)
{
if (null==ctl) return;
ctl.style.display
= isShow?(_display||"inline"):"none";
ctl.style.visibility
= isShow?"visible":"hidden";
}


// 展开/折叠 显示
function click_show(ctl)
{
var s = ctl.value;
var isShow = ("+"==s);
ctl.value
= isShow?"-":"+";
var divdoc = ctl.parentNode.lastChild;
setShow(divdoc, isShow);
}

// 显示xml
function showxml(urlPath, divdoc, xmlDoc)
{
if (null==divdoc) return;
if (null==xmlDoc)
{
divdoc.innerHTML
="error!";
return;
}
// == main ==
//divdoc.innerHTML = xml_transformNode(xmlDoc, xsl);
//divdoc.innerHTML = "OK!";
// Parse
var sall =""; // 所有内容
var nodes=xmlDoc.documentElement.childNodes;
for(var i=0; i<nodes.length; i++) // 第一级。sdk:platform, sdk:sample, ...
{
var nod = nodes[i];
var stag = nod.nodeName.substr(4); // 标签名
if (1==nod.nodeType) // 节点类型为元素时
{
var nod2 = nod.selectSingleNode("sdk:archives"); // 第二级。sdk:archives(文件集)
if (null!=nod2) // 当文件集存在时才添加
{
// 读取参数
var sapilevel = xml_text(nod.selectSingleNode("sdk:api-level"));
var srevision = xml_text(nod.selectSingleNode("sdk:revision"));
var sdescription = xml_text(nod.selectSingleNode("sdk:description"));
// 标题
var stitle = stag +"(";
if (""!=sapilevel) stitle += sapilevel +", ";
stitle
+="r"+ srevision +"): "+ sdescription;
// 添加
sall +="<h2>"+ stitle +"</h2>\n";
// 档案
for(var i3=0; i3<nod2.childNodes.length; i3++) // 第三级。sdk:archive
{
var nod3 = nod2.childNodes[i3];
if ("sdk:archive"==nod3.nodeName)
{
var surl = xml_text(nod3.selectSingleNode("sdk:url"));// 下载地址
if (null!=surl)
{
if (surl.indexOf("//")<0) surl = urlPath + surl; // 将相对路径转为绝对路径
// 添加url
//sall += "" + surl + "<br/>\n"; // 文本模式
sall +="<a href='"+ surl +"'>"+ surl +"</a><br/>\n"; // 链接模式
}
}
}
}
}
}
divdoc.innerHTML
= sall;
}

// 加载xml
function doload(url, desc)
{
// 创建边框div
var divrect = document.createElement("div");
divrect.className
="div_border";
divrect.title
= url;
divrect.innerHTML
="<input type='button' value='-' onclick='click_show(this)'>"+
"&nbsp;"+ url +"<br />"+
((
""!=desc)?("<b>desc</b>: "+ desc +"<br />"):"")+
"<div name='divdoc'>loading...</div>";

// add
var divShow = getRef("divShow");
divShow.appendChild(divrect);
divShow.appendChild(document.createElement(
"br")); // 空一行

// 计算路径
var urlPath ="http://dl.google.com/android/repository/"; // 默认路径
if (url.indexOf("//")>=0)
{
// 是外网路径,进行转换
urlPath = url.substr(0, url.lastIndexOf("/")+1);
}

// 加载xml
xml_loadFile(url, function(xmlDoc, isError){
// 用xsl转换xml
var divdoc = divrect.lastChild;
showxml(urlPath, divdoc, isError
?null:xmlDoc);
});
}

// 处理附加SDK列表
function onload_addons(xmlDoc, isError)
{
// UI
var divAddons = getRef("divAddons");
if (isError)
{
divAddons.innerHTML
="addons_list-1.xml: error!"
return;
}
setShow(divAddons,
false); // 加载成功,隐藏本div

// Parse
var nodes=xmlDoc.documentElement.childNodes;
for(var i=0; i<nodes.length; i++)
{
var nod = nodes[i];
if ("sdk:addon-site"==nod.nodeName)
{
var sUrl = xml_text(nod.selectSingleNode("sdk:url"));
var sName = xml_text(nod.selectSingleNode("sdk:name"));
// load
doload(sUrl, sName);
}
}
}

// 初始化
function init()
{
// Load main
doload("http://dl.google.com/android/repository/repository-5.xml", "main");

// Load addons_list
xml_loadFile("http://dl.google.com/android/repository/addons_list-1.xml", onload_addons);
}
</script>
</head>
<body onload="init()">
<h1>Anroid SDK URL(安卓SDK地址)</h1><br />
<div id="divShow"></div>
<div id="divAddons" class="div_border">addons_list-1.xml: loading...</div>
</body>
</html>

 

 

3.4 小结

 

  运行效果为——

 

  成功的显示了其他厂商的SDK,而且下载地址正确。

 

  还有可以改进的地方吗?仔细观察后发现,现在存在1点不足——

1.按“API Level”分类。现在实际上是按资源(repository)分类的,但在很多情况下我们只关心特定的API级别。所以SDK Manager默认是以“API Level”分类的。

 

  怎么办呢?请听下回分解。

 

posted on 2011-11-28 16:20  zyl910  阅读(1077)  评论(0编辑  收藏  举报