XmlUtils JS操作XML工具類
更新時(shí)間:2009年10月01日 01:27:30 作者:
經(jīng)常用到對(duì)xml的操作,Java里面有dom和dom4j等工具類,但是Javascript就沒有,所以自己寫了一個(gè),目前算作第一個(gè)版本吧??隙ㄟ€有很多地方需要改進(jìn),如果有需要用的朋友,可以把bug和需要完善改進(jìn)的地方留言或評(píng)論。
demo用了點(diǎn)extjs的東西,主要是為了打印json數(shù)組出來。
js code(XmlUtils.js):
復(fù)制代碼 代碼如下:
/**/
function XmlUtils (config) {
/*定義私有屬性*/
this.isIE = !!(window.attachEvent && !window.opera);
this.init();
if(config) {
this.dataType = config.dataType == 'json' ? 'json' : 'array';
if(config.xmlPath) this.loadXml(config.xmlPath);
}
}
XmlUtils.prototype = {
xmlDoc : null,
xmlPath : null,
dataType : null,
/**
* 初始化
*/
init : function () {
if (this.isIE) {
var activexArr = ["MSXML4.DOMDocument", "MSXML3.DOMDocument", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XmlDom"];
for(i=0; i<activexArr.length; i++){
try{
this.xmlDoc = new ActiveXObject(activexArr[i]);
}catch(e){}
}
} else {
this.xmlDoc = document.implementation.createDocument("", "", null);
}
},
/**
* 加載xml文件,參數(shù):
* @param {string} xmlPath:加載的xml文件路徑;
* @return {Object} true 正常加載; false 加載失敗
*/
loadXml : function (xmlPath) {
try {
this.xmlDoc.async = false;
this.xmlDoc.load(xmlPath);
this.xmlPath = xmlPath;
return true;
} catch (e) {
return false;
}
},
/**
* 加載XML字符串
* @param {Object} XMLString
*/
loadXmlString: function(xmlString) {
if (this.isIE) {
this.xmlDoc.loadXML(xmlString);
} else {
var parser = new DOMParser();
this.XMLDoc = parser.parseFromString(xmlString, "text/xml");
}
},
/**
* 判斷節(jié)點(diǎn)的是否有子節(jié)點(diǎn)
* @param {Object} node
* @return {Object} 有子節(jié)點(diǎn)則返回true,否則返回false
*/
hasChildNodes : function (node) {
return node.hasChildNodes();
},
/**
* 判斷節(jié)點(diǎn)的是否有屬性
* @param {Object} node
* @return {Object} 有屬性則返回true,否則返回false
*/
hasAttributes : function (node) {
return (node.attributes.length > 0) ? true : false;
},
/**
* 判斷節(jié)點(diǎn)的是否是文本節(jié)點(diǎn),包括帶CDATA區(qū)段的文本節(jié)點(diǎn)
* @param {Object} node
* @return {Object} 是文本節(jié)點(diǎn)則返回true,否則返回false
*/
isTextNode : function (node) {
var type = this.getNodeType(node);
return (type == 3 || type == 4) ? true : false;
},
/**
* 返回根節(jié)點(diǎn)
* @return {Object} 根節(jié)點(diǎn)
*/
getRoot : function () {
return this.xmlDoc.documentElement;
},
/**
* 返回節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn),沒有參數(shù)則返回根節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)
* @param {Object} node
* @return {Object} 節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)
*/
getFirstChild : function (node) {
return node ? node.firstChild : this.getRoot().firstChild;
},
/**
* 返回節(jié)點(diǎn)的最后子節(jié)點(diǎn),沒有參數(shù)則返回根節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)
* @param {Object} node
* @return {Object} 節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)
*/
getLastChild : function (node) {
return node ? node.lastChild : this.getRoot().lastChild;
},
/**
* 返回節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),沒有參數(shù)則返回根節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)
* @param {Object} node
* @return {Object} 節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)
*/
getNextNode : function (node) {
return node ? node.nextSibling : null;
},
/**
* 返回節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn),沒有參數(shù)則返回根節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)
* @param {Object} node
* @return {Object} 節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)
*/
getPreviousNode : function (node) {
return node ? node.previousSibling : null;
},
/**
* 返回節(jié)點(diǎn)的子節(jié)點(diǎn),沒有參數(shù)則返回null
* @param {Object} node
* @return {Object} 節(jié)點(diǎn)所有子節(jié)點(diǎn)
*/
getChildNodes : function (node) {
return (node && this.hasChildNodes(node)) ? node.childNodes : null;
},
/**
* 返回節(jié)點(diǎn)的父節(jié)點(diǎn),沒有參數(shù)則返回null
* @param {Object} node
* @return {Object} 節(jié)點(diǎn)父節(jié)點(diǎn)
*/
getParentNode : function (node) {
return node ? node.parentNode : null;
},
/**
* 根據(jù)節(jié)點(diǎn)名返回節(jié)點(diǎn)數(shù)組文本值,參數(shù):
* @param {string或object} nodeName:節(jié)點(diǎn)名稱;
* @return {object} 節(jié)點(diǎn)存在返回節(jié)點(diǎn)數(shù)組;節(jié)點(diǎn)不存在則返回null。
*/
getNodesTextByName : function (nodeNames) {
return nodeNames ? (this.dataType == 'json' ? this.getJsonNodesTextByName(nodeNames) : this.getArryNodesTextByName(nodeNames)) : null;
},
/**
* 根據(jù)節(jié)點(diǎn)名返回節(jié)點(diǎn)普通數(shù)組文本值,參數(shù):
* @param {string或object} nodeName:節(jié)點(diǎn)名稱;
* @return {object} 節(jié)點(diǎn)存在返回節(jié)點(diǎn)普通數(shù)組。
*/
getArryNodesTextByName : function (nodeNames) {
var rs = [];
//返回普通數(shù)組格式
switch (typeof(nodeNames)) {
case 'string':
var nodes = this.getNodesByTagName(nodeNames);
for (var i = 0; i < nodes.length; i++) {
rs.push(nodes[i].text);
}
break;
case 'object':
var subRs;
var nodes;
for (var i = 0; i < nodeNames.length; i++) {
nodes = this.getNodesByTagName(nodeNames[i]);
subRs = [];
for (var j = 0; j < nodes.length; j++) {
subRs.push(nodes[j].text);
}
rs.push(subRs);
}
break;
}
return rs;
},
/**
* 根據(jù)節(jié)點(diǎn)名返回節(jié)點(diǎn)JSON數(shù)組文本值,參數(shù):
* @param {string或object} nodeName:節(jié)點(diǎn)名稱;
* @return {object} 節(jié)點(diǎn)存在返回節(jié)點(diǎn)JSON數(shù)組;節(jié)點(diǎn)不存在則返回null。
*/
getJsonNodesTextByName : function (nodeNames) {
var rs = null;
//返回JSON數(shù)組格式
switch (typeof(nodeNames)) {
case 'string':
eval('rs = {' + nodeNames + ':[]}');
var nodes = this.getNodesByTagName(nodeNames);
for (var i = 0; i < nodes.length; i++) {
eval('rs.' + nodeNames + '.push({' + nodeNames + i + ': nodes[i].text})');
}
break;
case 'object':
rs = {};
var nodes;
for (var i = 0; i < nodeNames.length; i++) {
eval('rs.' + nodeNames[i] + '=[]');
nodes = this.getNodesByTagName(nodeNames[i]);
for (var j = 0; j < nodes.length; j++) {
eval('rs.' + nodeNames[i] + '.push({' + nodeNames[i] + j + ': nodes[j].text})');
}
}
break;
}
return rs;
},
/**
* 根據(jù)節(jié)點(diǎn)屬性得到節(jié)點(diǎn),參數(shù):
* @param {String} key:屬性名,默認(rèn)是id
* @param {String} value:屬性值
* @return {String} 符合條件的節(jié)點(diǎn)數(shù)組。
*/
getNodesByAttribute : function (key, value) {
key = key ? key : 'id';
value = value ? value : '';
return id ? this.xmlDoc.getElementById(id) : null;
},
/**
* 根據(jù)節(jié)點(diǎn)名得到節(jié)點(diǎn),參數(shù):
* @param {string} tagName:節(jié)點(diǎn)名稱
* @return {string} 指定節(jié)點(diǎn)名字的和位置的節(jié)點(diǎn)或節(jié)點(diǎn)數(shù)組。
*/
getNodesByTagName : function (tagName) {
return tagName ? this.xmlDoc.getElementsByTagName(tagName) : null;
},
/**
* 根據(jù)節(jié)點(diǎn)路徑返回第index個(gè)節(jié)點(diǎn),參數(shù):
* @param {string} xPath:節(jié)點(diǎn)路徑
* @param {number}index:要索引的位置,為空或0則返回所有查找到的節(jié)點(diǎn)。
* @return {string} 指定節(jié)點(diǎn)名字的和位置的節(jié)點(diǎn)或節(jié)點(diǎn)數(shù)組。
*/
getNodesByXpath : function (xPath, index) {
if (!xPath) return null;
var nodes = this.xmlDoc.selectNodes(xPath);
var len = nodes.length;
if(!index || index > len || index < 0) return nodes;
for(var i=0; i<len; i++){
if(i == index - 1) return nodes[i];
}
},
/**
* 得到指定節(jié)點(diǎn)文本,參數(shù):
* @param {object} node:節(jié)點(diǎn)
* @return {string} 節(jié)點(diǎn)文本,為空則返回null
*/
getText : function (node) {
return node ? node.text : null;
},
/**
* 得到指定節(jié)點(diǎn)名稱,參數(shù):
* @param {object} node:節(jié)點(diǎn)
* @return {string} 節(jié)點(diǎn)名稱,為空則返回null
*/
getTagName : function (node) {
return node ? node.nodeName : null;
},
/**
* 返回節(jié)點(diǎn)類型,參數(shù):
* @param {object} node:節(jié)點(diǎn)
* @return {string} 節(jié)點(diǎn)類型,為空則返回null
* 1-element
* 2-attribute
* 3-text
* 4-cdata
* 5-entity reference
* 6-entity
* 7-pi (processing instruction)
* 8-comment
* 9-document
* 10-document type
* 11-document fragment
* 12-notation
*/
getNodeType : function (node) {
return node ? node.nodeType : null;
},
/**
* 創(chuàng)建節(jié)點(diǎn),參數(shù):
* @param {string} nodeName:節(jié)點(diǎn)名稱,必填
* @param {string} text:節(jié)點(diǎn)文本,可為空
* @param {Object} attributes:屬性值-JSON數(shù)組,可為空,例:{id:'id001',name:'name001'}
* @param {Object} node:要增加子節(jié)點(diǎn)的節(jié)點(diǎn),為空則返回新建的節(jié)點(diǎn)
* @param {Boolean} cdata:是否生成帶有CDATA區(qū)段的節(jié)點(diǎn),true:生成,false:不生成
* @return {Object} 創(chuàng)建的節(jié)點(diǎn),有異常則返回null
*/
createNode: function(nodeName, text, attributes, node, cdata) {
if (this.isIE) {
//創(chuàng)建子接點(diǎn)
var childNode = this.xmlDoc.createElement(nodeName);
//創(chuàng)建文本節(jié)點(diǎn)
var textNode = cdata == true ? this.xmlDoc.createCDATASection(text) : this.xmlDoc.createTextNode(text);
childNode.appendChild(textNode);
//添加屬性
for (var i in attributes) {
this.createAttribute(childNode,i,attributes[i]);
};
return node ? node.appendChild(childNode) : childNode;
} else {
alert('FF創(chuàng)建節(jié)點(diǎn)再說.');
return null;
}
},
/**
* 創(chuàng)建帶CDATA區(qū)段的節(jié)點(diǎn),參數(shù):
* @param {string} nodeName:節(jié)點(diǎn)名稱,必填
* @param {string} text:節(jié)點(diǎn)文本,可為空
* @param {Object} attributes:屬性值-JSON數(shù)組,可為空,例:{id:'id001',name:'name001'}
* @param {Object} node:要增加子節(jié)點(diǎn)的節(jié)點(diǎn),為空則返回新建的節(jié)點(diǎn)
*/
createCDATANode: function(nodeName, text, attributes, node) {
this.createNode(nodeName, text, attributes, node, true);
},
/**
* 創(chuàng)建節(jié)點(diǎn)屬性,參數(shù):
* @param {Object} node:節(jié)點(diǎn),必填
* @param {String} key:屬性名,必填
* @param {Object} value:屬性值,必填
* @param {Object} node:返回新增屬性的節(jié)點(diǎn)
* @return {Object} 增加屬性的節(jié)點(diǎn),有異常則返回null
*/
createAttribute: function(node, key, value) {
if (this.isIE) {
if(!key) return;
var attr = this.xmlDoc.createAttribute(key);
attr.value = value ? value : "";
node.setAttributeNode(attr);
return node;
} else {
alert('FF創(chuàng)建節(jié)點(diǎn)再說.');
return node;
}
return null;
},
/**
* 把節(jié)點(diǎn)加到根節(jié)點(diǎn)上,參數(shù):
* @param {Object} node:節(jié)點(diǎn)
* @return {Object} 有異常則返回null
*/
addNodeToRoot: function(node) {
if(!node) return null;
this.getRoot().appendChild(node);
return node;
},
/**
* 把節(jié)點(diǎn)加到另外節(jié)點(diǎn)上,參數(shù):
* @param {Object} node:節(jié)點(diǎn)
*/
addNode: function(node,childNode) {
return (node && childNode) ? node.appendChild(childNode) : false;
},
/**
* 從父節(jié)點(diǎn)移除節(jié)點(diǎn)自身,參數(shù):
* @param {Object} newNode:要替換的節(jié)點(diǎn)
* @param {Object} oldNode:要被替換的節(jié)點(diǎn)
*/
replaceChild: function(newNode, oldNode) {
var parentNode = oldNode.parentNode;
if(!newNode || !oldNode || !parentNode) return;
parentNode.replaceChild(newNode, oldNode);
},
/**
* 從父節(jié)點(diǎn)移除節(jié)點(diǎn)自身,參數(shù):
* @param {Object} node:要移除的節(jié)點(diǎn)
*/
removeChild: function(node) {
if(!node || !node.parentNode) return;
node.parentNode.removeChild(node);
},
/**
* 移除節(jié)點(diǎn)的所有子節(jié)點(diǎn),參數(shù):
* @param {Object} node:父節(jié)點(diǎn)
*/
removeChildNodes: function(node) {
if (node && this.hasChildNodes(node)) {
var childNodes = node.childNodes;
for(var i = 0; i < childNodes.length; i++) {
node.removeChild(childNodes[0]);
}
}
},
/**
* 設(shè)置節(jié)點(diǎn)屬性值,不存在則新建,參數(shù):
* @param {Object} node:要設(shè)置的節(jié)點(diǎn)
* @param {String} key:要設(shè)置的屬性名
* @param {String} value:要設(shè)置的屬性值
*/
setAttribute: function(node, key, value) {
this.createAttribute(node, key, value);
},
/**
* 設(shè)置文本節(jié)點(diǎn)的文本,參數(shù):
* @param {Object} node:要設(shè)置的節(jié)點(diǎn)
* @param {String} text:要設(shè)置的文本
*/
setText: function(node, text) {
if(this.isTextNode(node)) node.text = text;
},
/**
* 在文本節(jié)點(diǎn)后面追加文本,參數(shù):
* @param {Object} node:要設(shè)置的節(jié)點(diǎn)
* @param {String} text:要設(shè)置的文本
*/
appendText: function(node, text) {
if(this.isTextNode(node)) node.appendData(text);
},
/**
* 輸出xml,為空則輸出根節(jié)點(diǎn)文本,參數(shù):
* @param {Object} node:要輸出的節(jié)點(diǎn)
*/
toString: function(node) {
node = node ? node : this.xmlDoc.documentElement;
if (typeof node == 'string') return node;
return this.isIE ? node.xml : new XMLSerializer().serializeToString(node);
}
}
測試的xml文件(book.xml):
復(fù)制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<root>
<book>
<name>西游記</name>
<author>吳承恩</author>
</book>
<book>
<name>紅樓夢</name>
<author>曹雪芹</author>
</book>
<book>
<name>三國演義</name>
<author>
<name>施耐庵</name>
<sex>男</sex>
</author>
</book>
<book>
<name>水滸傳</name>
<author>羅貫中</author>
</book>
</root>
html code (test.html):
復(fù)制代碼 代碼如下:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script language="JavaScript" type="text/javascript" src="../Ext/ext-base.js" ><!--
// --></script>
<script language="JavaScript" type="text/javascript" src="../Ext/ext-all.js" ><!--
// --></script>
<title>測試xml</title>
<script src="XmlUtils.js"></script>
</head>
<body>
<div id='xmlOpTest'></div>
</body>
<script type="text/javascript"><!--
/**
* config參數(shù):xmlPath文件地址;dataType數(shù)據(jù)格式-json或arry,默認(rèn)為array。
*/
var xmlUtils = new XmlUtils({xmlPath:"book.xml",dataType:'json'});
alert(xmlUtils.toString());
var rs = xmlUtils.getNodesTextByName(['name','author']);
//把上面的dataType改為array或者不為json此處就能得到值
document.getElementById('xmlOpTest').innerHTML += '<br/>取得所有的文本節(jié)點(diǎn)的數(shù)組: '+rs + '<br/>';
//這里用了Ext的json解析工具 Ext.encode這個(gè)方法是把json對(duì)象轉(zhuǎn)換為字符串。Ext.decode則相反,把json格式的字符串轉(zhuǎn)換為json對(duì)象數(shù)組
document.getElementById('xmlOpTest').innerHTML += '<br/>取得所有的文本節(jié)點(diǎn)的JSON數(shù)組: '+Ext.encode(rs)+'<br/>';
var root = xmlUtils.getRoot();
xmlUtils.createNode('publish', '中國電力出版社',{id:'id0001'},root);
xmlUtils.createCDATANode('publish', '中國&電力出版社',{},root);
//設(shè)置屬性
xmlUtils.setAttribute(root,'testId','test');
//修改屬性
xmlUtils.setAttribute(root,'testId','test0000000000');
alert(xmlUtils.toString(root));
xmlUtils.removeChild(xmlUtils.getNodesByXpath('//root/publish')[0]);
alert(xmlUtils.toString(root));
node = xmlUtils.getFirstChild();
document.getElementById('xmlOpTest').innerHTML += '<br/>判斷是否有子節(jié)點(diǎn): '+xmlUtils.hasChildNodes(node) + ' ------ 判斷是否有屬性:';//+ xmlUtils.hasAttributes(node) +'<br/>';
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn): '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +' ======== 節(jié)點(diǎn)類型:' + xmlUtils.getNodeType(node) + '<br/>';
node = xmlUtils.getNextNode(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn)下一個(gè)節(jié)點(diǎn): '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +'<br/>';
node = xmlUtils.getLastChild();
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節(jié)點(diǎn)的最后一個(gè)節(jié)點(diǎn): '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +'<br/>';
node = xmlUtils.getPreviousNode(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節(jié)點(diǎn)的最后一個(gè)前一個(gè)節(jié)點(diǎn): '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +'<br/>';
node = xmlUtils.getParentNode(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節(jié)點(diǎn)的父節(jié)點(diǎn): '+ xmlUtils.toString(node) +'<br/>';
var nodes = xmlUtils.getChildNodes();
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節(jié)點(diǎn)的所有子節(jié)點(diǎn): '+xmlUtils.toString(nodes)+'<br/>';
node = xmlUtils.getNodesByXpath('//root/book/name',2);
document.getElementById('xmlOpTest').innerHTML += '<br/>根據(jù)xPath得到節(jié)點(diǎn)名稱和文本值: '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node)+'<br/>';
node = xmlUtils.getNodesByXpath('//root/book/author');
document.getElementById('xmlOpTest').innerHTML += '<br/>根據(jù)xPath得到節(jié)點(diǎn)名稱和文本值: '+xmlUtils.getTagName(node[0]) + "---" + xmlUtils.getText(node[0])+'<br/>';
//得到修改后的文本節(jié)點(diǎn)
node = xmlUtils.getNodesByXpath('//root/publish',1);
node = xmlUtils.getFirstChild(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>修改文本值前節(jié)點(diǎn)文本: '+xmlUtils.getText(node);
xmlUtils.setText(node,"西游記后傳");
document.getElementById('xmlOpTest').innerHTML += '-----修改文本值后節(jié)點(diǎn)文本: '+xmlUtils.getText(node);
xmlUtils.appendText(node,"之測試");
document.getElementById('xmlOpTest').innerHTML += '-----追加文本值后節(jié)點(diǎn)文本: '+xmlUtils.getText(node) + "<br/>";
// --></script>
</html>
上面的文件都上傳了,正在審核中,等審核通過了我會(huì)發(fā)到這里的。
相關(guān)文章
Bootstrap免費(fèi)字體和圖標(biāo)網(wǎng)站(值得收藏)
在這篇內(nèi)容中,我們把這套框架上的免費(fèi)字體圖標(biāo)做了個(gè)整合(當(dāng)然,以后還會(huì)不斷的更新)。大家對(duì)bootstrap免費(fèi)字體圖標(biāo)有需要的話,可以參考本教程2017-03-03uni-app調(diào)取接口的3種方式以及封裝uni.request()詳解
我們?cè)趯?shí)際工作中要將數(shù)據(jù)傳輸?shù)椒?wù)器端,從服務(wù)器端獲取信息,都是通過接口的形式,下面這篇文章主要給大家介紹了關(guān)于uni-app調(diào)取接口的3種方式以及封裝uni.request()的相關(guān)資料,需要的朋友可以參考下2022-08-08js動(dòng)態(tài)拼接正則表達(dá)式的兩種方法
這篇文章主要介紹了js動(dòng)態(tài)拼接正則表達(dá)式的兩種方法,需要的朋友可以參考下2014-03-03在iframe中使bootstrap的模態(tài)框在父頁面彈出問題
這篇文章主要介紹了在iframe中使bootstrap的模態(tài)框在父頁面彈出問題,解決方法非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-08-08微信sdk實(shí)現(xiàn)禁止微信分享(使用原生php實(shí)現(xiàn))
這篇文章主要介紹了微信sdk實(shí)現(xiàn)禁止微信分享(使用原生php實(shí)現(xiàn)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11layui結(jié)合form,table的全選、反選v1.0示例講解
今天小編就為大家分享一篇layui結(jié)合form,table的全選、反選v1.0示例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08