Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

finish 0.1.0

  • Loading branch information...
commit 65d95964d94e108152c26304a13b15f1d47e4377 1 parent e32428c
U-IE361-PC\Administrator authored
View
2  ant/build.properties
@@ -2,7 +2,7 @@
### Build settings
######################################################################
-build.version = 1.0.0
+build.version = 0.1.0
build.name = jsxml-${build.version}
build.files = jsxml.js
View
12 ant/java.exe.stackdump
@@ -1,12 +0,0 @@
-Exception: STATUS_ACCESS_VIOLATION at eip=610C7B39
-eax=00000000 ebx=00000001 ecx=00000000 edx=0000068C esi=00000000 edi=0112CCC8
-ebp=0112CB04 esp=0112CADC program=\\?\C:\Program Files\Java\jre6\bin\java.exe, pid 27748, thread unknown (0x7920)
-cs=001B ds=0023 es=0023 fs=003B gs=0000 ss=0023
-Stack trace:
-Frame Function Args
-0112CB04 610C7B39 (00000000, 00000000, 00000000, 00000000)
-0112CC14 610C84D5 (00000000, 00000000, 00000000, 00000000)
-0112CCD4 610C923A (FFFFFFFF, FFFFFFFF, 00000000, 00000000)
-0112CD24 61028142 (00000002, 0112CE64, 00000002, 0112CDF4)
-0112CDB8 7C87655C (00000002, 0112CDF4, 7C8763C0, 00000002)
-End of stack trace
View
75 examples/weather.html
@@ -0,0 +1,75 @@
+<!doctype>
+<html>
+<head>
+<meta charset="utf-8">
+<title>jsxml example - Yahoo weather</title>
+</head>
+<style>
+html{
+ background:#f2f2f2;
+}
+body{
+ padding-top:20px;
+ width:960px;
+ margin:0 auto;
+ text-align:center;
+ color:#404040;
+ font-family: 'Microsoft Yahei', Verdana, Arial;
+ text-shadow:#fff 1px 0px 1px;
+}
+
+ol{
+ list-style:none;
+}
+
+#container{
+ text-align:left;
+}
+</style>
+<body>
+<h1>jsxml example - Yahoo weather</h1>
+<button id="btn">fetch weather data</button>
+<div id="container">
+</div>
+<script src="http://cdnjs.cloudflare.com/ajax/libs/yui/3.3.0/yui-min.js"></script>
+<script src="../src/jsxml.js"></script>
+<script>
+YUI().use('node-base', 'yql', 'substitute', function(Y){
+ //http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20location%3D'CHXX0044'
+ var query = "select * from weather.forecast where location='CHXX0044'";
+ var XML = jsxml.XML;
+ var init = function(){
+ var list = xml.descendants('forecast'),
+ template = "{date},{day},天气{weather},最高气温{high},最低气温{low}。",
+ innerHTML = '<h2>'+xml.child('item').child('title').getValue()+'</h1>';
+
+ innerHTML += '<h3>天气预报</h3><ol>';
+ list.each(function(item, index){
+ var html = Y.substitute(template, {
+ date: item.attribute('date').getValue(),
+ day: item.attribute('day').getValue(),
+ high: item.attribute('high').getValue(),
+ low: item.attribute('low').getValue(),
+ weather: item.attribute('text').getValue()
+ });
+ innerHTML += '<li>'+html +'</li>';
+ });
+ innerHTML += '</ol>';
+ innerHTML += "<h3>详情</h3>";
+ innerHTML += "<div>"+xml.child('item').child('description').getValue() + "</div>";
+ Y.one('#container').setContent(innerHTML);
+ };
+ var getWeather = function(){
+ Y.one('#container').setContent('start fetching weather data...');
+ Y.YQL(query, function(r){
+ xml = new XML(r.results[0]);
+ init();
+ }, {format:'xml'});
+ }
+ Y.one('#btn').on('click', function(e){
+ getWeather();
+ });
+});
+</script>
+</body>
+</html>
View
1,479 src/jsxml.js
@@ -1,30 +1,127 @@
/*!
* Copyright 2011 http://colorhook.com.
* @author: <a href="colorhook@gmail.com">colorhook</a>
- * @version:1.0.0
+ * @version:0.1.0
*/
/**
* @preserve Copyright 2011 http://colorhook.com.
* @author: <a href="colorhook@gmail.com">colorhook</a>
- * @version:1.0.0
+ * @version:0.1.0
*/
-window.jsxml = (function(){
+var jsxml = (function(){
+ /**
+ * XML parser comes from HTML Parser by John Resig (ejohn.org)
+ * http://ejohn.org/files/htmlparser.js
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ */
// Regular Expressions for parsing tags and attributes
- var startTag = /^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
- endTag = /^<\/(\w+)[^>]*>/,
- attr = /(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g,
+ var startTag = /^<([a-zA-Z\$_]+:{0,1}[a-zA-Z0-9\$\-_]*)((?:\s+[a-zA-Z\$_]+:{0,1}[a-zA-Z0-9\$\-_]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
+ endTag = /^<\/([a-zA-Z0-9\$\-_:]+)[^>]*>/,
+ attr = /([a-zA-Z\$_]+:{0,1}[a-zA-Z0-9\$\-_]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g,
_parseXML,
+ trim,
+ merge,
+ containsEntity,
+ replaceToEntity,
+ replaceFromEntity,
Namespace,
QName,
NodeKind,
- XMLNode,
+ _getXMLIfLengthEqualOne,
XMLList,
XML;
-
-
- _parseXML = function(xml, handler ) {
+ /**
+ * @description trim whitespace before or after the String
+ * @param s{String}
+ * @return String
+ */
+ trim = String.prototype.trim ? function(s){
+ return s && s.trim ? s.trim() : s;
+ }: function(s){
+ try{
+ return s.replace(/^\s+|\s+$/, '');
+ }catch(err){
+ return s;
+ }
+ };
+ /**
+ * @description merge one object to another, used to extend object.
+ * because of the toString property is not enumerable in IE browser,
+ * so we must assign it explicity.
+ * @param s1{Object} object need to be extended.
+ * @param s2{Object} extension object
+ * @return Object
+ */
+ merge = function(s1, s2){
+ for(var i in s2){
+ if(s2.hasOwnProperty(i)){
+ s1[i] = s2[i];
+ }
+ }
+ //fix IE toString() not Enumerable bug
+ if(!-[1,]){
+ if(s2.toString !== Object.prototype){
+ s1.toString = s2.toString;
+ }
+ }
+ };
+ /**
+ * @description find element's index from an array.
+ * @param array{Array} the array hosting the element
+ * @param ele{Object} the element in the array
+ * @return Number
+ */
+ arrayIndexOf = function(array, ele){
+ if(array.indexOf){
+ return array.indexOf(ele);
+ }
+ for(var i = 0, l = array.length; i < l; i++){
+ if(ele === array[i]){
+ return i;
+ }
+ }
+ return -1;
+ };
+ /**
+ * @description check if the string contains XML entity format(&amp; &lt; &gt;) or not.
+ * @param str{String}
+ * @return Boolean
+ */
+ containsEntity = function(str){
+ return str.match(/&(amp|lt|gt);/);
+ };
+ /**
+ * @description convert special characters (& < >) to XML entity format.
+ * @param str{String}
+ * @return String
+ */
+ replaceToEntity = function(str){
+ str = str.replace(/&[^(amp;|lt;|gt;)]/g, '&amp;');
+ str = str.replace(/</g, '&lt;');
+ str = str.replace(/>/g, '&gt;');
+ return str;
+ }
+ /**
+ * @description convert from XML entity format to readable characters.
+ * @param str{String}
+ * @return String
+ */
+ replaceFromEntity = function(str){
+ str = str.replace(/&lt;/g, '<');
+ str = str.replace(/&gt;/g, '>');
+ str = str.replace(/&amp;/g, '&');
+ return str;
+ }
+ /**
+ * @description parse XML string
+ * @param xml{String} XML string
+ * @param handler{Object} callback handler
+ * @return void
+ */
+ _parseXML = function(xml, handler ) {
var index, chars, match, stack = [], last = xml;
stack.last = function(){
return this[ this.length - 1 ];
@@ -38,13 +135,11 @@ window.jsxml = (function(){
index = xml.indexOf("]]>");
if(index > 0){
- xml = xml.replace(new RegExp("(.*)<\/" + stack.last() + "[^>]*>"), function(all, text){
- text = text.replace(/<!--(.*?)-->/g, "$1").replace(/<!\[CDATA\[(.*?)]]>/g, "$1");
-
+ text = xml.substring(9, index);
+
if ( handler.chars )
- handler.chars( text );
-
- });
+ handler.chars( text, true );
+
xml = xml.substring( index + 3 );
}
chars = false;
@@ -85,7 +180,6 @@ window.jsxml = (function(){
// start tag
} else if ( xml.indexOf("<") == 0 ) {
match = xml.match( startTag );
-
if ( match ) {
xml = xml.substring( match[0].length );
match[0].replace( startTag, parseStartTag );
@@ -113,9 +207,7 @@ window.jsxml = (function(){
parseEndTag();
function parseStartTag(tag, tagName, rest, unary ) {
-
-
- parseEndTag( "", tagName );
+
unary = !!unary;
if ( !unary )
@@ -166,7 +258,10 @@ window.jsxml = (function(){
};
/**
- * @description Namespace
+ * @description Namespace class
+ * @access public
+ * @param prefix{String} the namespace prefix
+ * @param uri{String} the namespace uri.
*/
Namespace = function(prefix, uri){
var len = arguments.length;
@@ -181,82 +276,1372 @@ window.jsxml = (function(){
this.uri = "";
}
}
-
+
Namespace.prototype = {
constructor: Namespace,
+
+ /**
+ * @description to string
+ * @access public
+ * @return String
+ */
toString: function(){
return this.uri;
+ },
+ /**
+ * @description return a Namespace copy object
+ * @access public
+ * @return Namespace
+ */
+ copy: function(){
+ var ns = new Namespace();
+ ns.prefix = this.prefix;
+ ns.uri = this.uri;
+ return ns;
+ },
+ /**
+ * @description check if the two Namespace are equivalent
+ * @access public
+ * @return Boolean
+ */
+ equals: function(ns){
+ return this.prefix === ns.prefix && this.uri === ns.uri;
}
}
/**
- * @description QName
+ * @description QName class
+ * @access public
+ * @param uri {Namespace | String}
+ * @param localName {String}
*/
QName = function(uri, localName){
var len = arguments.length;
if(len >= 2){
this.uri = String(uri);
+ this._ns = (uri && uri.constructor == Namespace) ? uri : new Namespace(uri);
this.localName = String(localName);
}else if(len == 1){
this.uri = "";
+ this._ns = new Namespace();
this.localName = String(uri);
}else{
this.uri = "";
+ this._ns = new Namespace();
this.localName = "";
}
}
QName.prototype = {
constructor: QName,
+
+ /**
+ * @description to string
+ * @return String
+ */
toString: function(){
var r = this.uri ? this.uri + "::" : "";
return r +this.localName;
+ },
+ /**
+ * @description return a QName copy object
+ * @return QName
+ */
+ copy: function(){
+ var qn = new QName();
+ qn.uri = this.uri;
+ qn.localName = this.localName;
+ qn._ns = this._ns.copy();
+ return qn;
+ },
+ /**
+ * @description check if the two QName are equivalent
+ * @access public
+ * @return Boolean
+ */
+ equals: function(qname){
+ return this.localName == qname.localName && this._ns.equals(qname._ns);
+ }
+ }
+ /**
+ * @description parse a name & value to a QName
+ * @access internal
+ * @static
+ * @param name{String} namespace declaration name
+ * @param value{String} namespace declaration value
+ * @return QName
+ */
+ QName._format = function(name, value){
+ var temp = name.split(":"), prefix, localName;
+ if(temp.length==2){
+ prefix = temp[0];
+ localName = temp[1];
+ }else{
+ prefix = '';
+ localName = name;
}
+ return new QName(new Namespace(prefix, value), localName);
}
/**
- * @description NodeKind
+ * @description NodeKind class
+ * @static
*/
NodeKind = {
'ELEMENT': 'element',
'COMMENT': 'comment',
- 'PROCESSING_INSTRUCTION': 'processing-instruction',
+ 'PROCESSING_INSTRUCTIONS': 'processing-instructions',
'TEXT': 'text',
'ATTRIBUTE': 'attribute'
}
+
/**
- * @description XMLNode
+ * @description get a suitable class for XML operations by the XMLList.
+ * if the list contains only one child, then return the child XML.
+ * @return XML|XMLList
*/
- XMLNode= function(children, attributes, nodeKind){
- this.children = children || [];
- this.attributes = attributes || [];
- this._nodekind = nodeKind || NodeKind.ELEMENT;
- this._parent = null;
- }
- XMLNode.prototype = {
- constructor: XMLNode
+ _getXMLIfLengthEqualOne = function(list){
+ if(list._list && list.length() == 1){
+ return _getXMLIfLengthEqualOne(list._list[0]);
+ }
+ return list;
+ };
+ /**
+ * @description XMLList is a XML collection
+ * @param null
+ */
+ XMLList= function(){
+ this._list = [];
}
+ merge(XMLList.prototype, {
+ constructor: XMLList,
+
+ /**
+ * @description add a xml to the list
+ * @access private
+ * @return XMLList
+ */
+ _addXML: function(xml){
+ if(xml.constructor == XML){
+ this._list.push(xml);
+ }else if(xml.constructor == XMLList){
+ this._list = this._list.concat(xml._list);
+ }
+ return this;
+ },
+ /**
+ * @description get the list length
+ * @access public
+ * @return int
+ */
+ length: function(){
+ return this._list.length;
+ },
+ /**
+ * @description you cannot call this method in a list, only XML owns childIndex method.
+ * @access none
+ * @return void
+ */
+ childIndex: function(){
+ throw new Error("this method only availabe in single list XML");
+ },
+ /**
+ * @description return all the child by localName in this xml list.
+ * @access public
+ * @return XMLList | XML
+ */
+ child: function(p){
+ var list = new XMLList();
+ this.each(function(item){
+ var child = item.child(p);
+ if(child.length()){
+ list._addXML(child);
+ }
+ });
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return all the child in this xml list.
+ * @access public
+ * @return XMLList | XML
+ */
+ children: function(){
+ return this.child('*');
+ },
+ /**
+ * @description return a special attribute type child by parameter
+ * @access public
+ * @param p{String} if the p is '*', return all attributes
+ * @return XML | XMLList
+ * @see attributes
+ */
+ attribute: function(p){
+ var list = new XMLList();
+ this.each(function(item){
+ list._addXML(item.attribute(p));
+ });
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return all attribute type child.
+ * @access public
+ * @return XML | XMLList
+ * @see attribute
+ */
+ attributes: function(p){
+ return this.attribute('*');
+ },
+ /**
+ * @description find special elements child from the XMLList tree top.
+ * @access public
+ * @param p{String} the element localName, if the localName is '*', return all the element child.
+ * @return XML | XMLList
+ */
+ elements: function(p){
+ var list = new XMLList();
+ this.each(function(item){
+ list._addXML(item.elements(p));
+ });
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description find descendants child from the XMLList tree top.
+ * @access public
+ * @param p{String} the descendant localName, if the localName is '*', return all the descendants.
+ * @return XML | XMLList
+ */
+ descendants: function(p){
+ var list = new XMLList();
+ this.each(function(item){
+ list._addXML(item.descendants(p));
+ });
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description merge multi text childs nearby to one text child of each list item.
+ * @access public
+ * @return void
+ */
+ normalize: function(){
+ this.each(function(item){
+ item.normalize();
+ });
+ },
+ /**
+ * @description check if all the list item owns simple content only
+ * @access public
+ * @return Boolean
+ * @see hasComplexContent
+ */
+ hasSimpleContent: function(){
+ for(var i=0, l = this._list.length; i < l; i++){
+ var item = this._list[i];
+ if(item.constructor == XMLList ||
+ item.hasComplexContent()){
+ return false;
+ }
+ }
+ return true;
+ },
+ /**
+ * @description check if all the list item owns simple content only
+ * @access public
+ * @return Boolean
+ * @see hasSimpleContent
+ */
+ hasComplexContent: function(){
+ return !this.hasSimpleContent();
+ },
+ /**
+ * @description return the text type child
+ * @access public
+ * @return XML
+ */
+ text: function(){
+ var xml = new XMLList();
+ this.each(function(item){
+ if(item.constructor == XML){
+ var t = item.text();
+ if(t._text != ""){
+ xml._addXML(t);
+ }
+ }
+ });
+ return _getXMLIfLengthEqualOne(xml);
+ },
+ /**
+ * @description return the comment type child
+ * @access public
+ * @return XML | XMLList
+ */
+ comments: function(){
+ var xml = new XMLList();
+ this.each(function(item){
+ if(item.constructor == XML){
+ xml._addXML(item.comments());
+ }
+ });
+ return _getXMLIfLengthEqualOne(xml);
+ },
+ /**
+ * @description return the XML processing-instructions.
+ * @access public
+ * @return XMLList | XML
+ */
+ processingInstructions: function(){
+ var xml = new XMLList();
+ this.each(function(item){
+ if(item.constructor == XML){
+ xml._addXML(item.processingInstructions());
+ }
+ });
+ return _getXMLIfLengthEqualOne(xml);
+ },
+ /**
+ * @description return an XMLList copy object.
+ * @access public
+ * @return XMLList
+ */
+ copy: function(){
+ var list = new XMLList();
+ this.each(function(item, i){
+ list._list[i] = item.copy();
+ });
+ return list;
+ },
+ /**
+ * @description return toXMLString of all the list item
+ * @access public
+ * @return String
+ */
+ toXMLString: function(){
+ var s = [];
+ this.each(function(item){
+ s.push(item.toXMLString());
+ });
+ return s.join("\n");
+ },
+ /**
+ * @description return toString of all the list item.
+ * @access public
+ * @return String
+ */
+ toString: function(){
+ var s = "";
+ this.each(function(item){
+ s += item.toString();
+ });
+ return s;
+ },
+ //===================extension for javascript=================
+ /**
+ * @description return a special item by item index.
+ * @access public
+ * @param n{int} the item index
+ * @return XML
+ */
+ item: function(n){
+ return this._list[n];
+ },
+ /**
+ * @description for loop the list item.
+ * @access public
+ * @param func{Function} the callback handler
+ * @return void
+ */
+ each: function(func){
+ for(var i = 0, l = this._list.length; i <l; i++){
+ func(this._list[i], i, this);
+ }
+ }
+ });
/**
- * @description XML
+ * @description XML class
+ * @param str{String}
*/
XML = function(str){
-
- }
-
- XML.prototype = {
- constructor: XML
+ this._children = [];
+ this._attributes = [];
+ this._namespaces = [];
+ this._nodeKind = NodeKind.ELEMENT;
+ this._qname = null;
+ this._parent = null;
+ this._text = null;
+ this._useCDATA = false;
+
+ var current, self= this;
+ if(str){
+ _parseXML(str, {
+ start: function(tag, attrs, unary ){
+ var xml;
+ if(!current){
+ xml = self;
+ }else{
+ xml = new XML();
+ xml._parent = current;
+ }
+ xml._qname = QName._format(tag);
+ for(var i in attrs){
+ var attr = new XML();
+ attr._nodeKind = NodeKind.ATTRIBUTE;
+ var _qname;
+ if(attrs[i].name === 'xmlns'){
+ _qname = new QName(new Namespace('xmlns', attrs[i].value), '');
+ }else{
+ _qname = QName._format(attrs[i].name, attrs[i].value);
+ }
+ var prefix = _qname._ns.prefix || "";
+
+ if(prefix === 'xmlns'){
+ var ns = new Namespace(_qname.localName, _qname.uri);
+ xml.addNamespace(ns);
+ if(_qname.localName == xml._qname._ns.prefix){
+ xml.setNamespace(ns);
+ }
+ }else{
+ attr._qname = _qname;
+ attr._text = attrs[i].value;
+ xml._attributes.push(attr);
+ }
+ }
+ current = xml;
+ if(unary){
+ this.end(tag);
+ }
+ },
+ chars: function(text, useCDATA){
+ text = trim(text);
+ if(text == "" && XML.ignoreWhitespace){
+ return;
+ }
+ var el = new XML();
+ el._nodeKind = NodeKind.TEXT;
+ el._text = text;
+ el._useCDATA = useCDATA;
+ current._children.push(el);
+ },
+ end: function(tag){
+ if(current && current._parent){
+ current._parent._children.push(current);
+ current = current._parent;
+ }else if(current == self){
+ current = null;
+ }
+ },
+ comment: function(value){
+ var el = new XML();
+ el._nodeKind = NodeKind.COMMENT;
+ el._text = value;
+ current && current._children.push(el);
+ },
+ instruction: function(value){
+ var el = new XML();
+ el._nodeKind = NodeKind.PROCESSING_INSTRUCTIONS;
+ el._text = value;
+ current && current._children.push(el);
+ }
+ });
+ }
}
+
+ merge(XML.prototype, {
+ /**
+ * @description add new namespace to this XML
+ * @access public
+ * @param ns{Namespace}
+ * @return void
+ */
+ addNamespace: function(ns){
+ if(ns.prefix !=undefined){
+ this.removeNamespace(ns);
+ this._namespaces.push(ns);
+ }
+ },
+ /**
+ * @description remove a namespace from this XML
+ * @access public
+ * @param ns{Namespace}
+ * @return void
+ */
+ removeNamespace: function(ns){
+ for(var i = 0, l = this._namespaces.length; i < l; i++){
+ if(ns.prefix==this._namespaces[i].prefix){
+ this._namespaces.splice(i, 1);
+ break;
+ }
+ }
+ },
+ /**
+ * @description reture a namespace by prefix
+ * @access public
+ * @param prefix{String}
+ * @return Namespace
+ */
+ namespace: function(prefix){
+ if(!prefix){
+ return new Namespace();
+ }
+ for(var i = 0, l = this._namespaces.length; i < l; i++){
+ if(prefix==this._namespaces[i].prefix){
+ return this._namespaces[i];
+ }
+ }
+ return undefined;
+ },
+ /**
+ * @description set the namespace for this XML
+ * @access public
+ * @param ns{Namespace}
+ * @return void
+ */
+ setNamespace: function(ns){
+ if(ns && ns.constructor == Namespace){
+ this.addNamespace(ns);
+ if(this._qname){
+ this._qname.uri = ns.uri;
+ this._qname._ns = ns;
+ }
+ }
+ },
+ /**
+ * @description return declarated namespace of this XML
+ * @access public
+ * @return Array
+ */
+ namespaceDeclarations: function(){
+ return this._namespaces;
+ },
+ /**
+ * @description return declarated namespace of this XML and all parent XML.
+ * @access public
+ * @return Array
+ */
+ inScopeNamespaces: function(){
+ var array = this._namespaces;
+ var chain = this._parent;
+ while(chain){
+ array = chain.inScopeNamespaces().concat(array);
+ chain = chain._parent;
+ }
+ return array;
+ },
+ /**
+ * @description return the nodekind of this element
+ * @access public
+ * @return String
+ * @see NodeKind
+ */
+ nodeKind: function(){
+ return this._nodeKind;
+ },
+ /**
+ * @description return the full name (with declarated namespace) of this xml
+ * @access public
+ * @return String
+ * @see localName
+ */
+ name: function(){
+ if(!this._qname){
+ return null;
+ }
+ if(this._qname.uri){
+ return this._qname.uri +":"+this._qname.localName;
+ }
+ return this._qname.localName;
+ },
+ /**
+ * @description return the local name (without declarated namespace) of this xml
+ * @access public
+ * @return String
+ * @see name
+ */
+ localName: function(){
+ if(!this._qname){
+ return null;
+ }
+ return this._qname.localName;
+ },
+ /**
+ * @description set the full name (with declarated namespace) of this xml
+ * @access public
+ * @return void
+ * @see name
+ */
+ setName: function(name){
+ if(this._qname == null){
+ return;
+ }
+ if(/^[a-zA-Z]+[a-zA-Z0-9]*$/.test(name)){
+ this._qname.uri = "";
+ this._qname.localName = name;
+ }else{
+ throw new Error("invalid value for XML name");
+ }
+ },
+ /**
+ * @description set the local name (without declarated namespace) of this xml
+ * @access public
+ * @return void
+ * @see localName
+ */
+ setLocalName: function(name){
+ if(this._qname == null){
+ return;
+ }
+ if(/^[a-zA-Z\$_]+[a-zA-Z0-9\$\-_]*$/.test(name)){
+ this._qname.localName = name;
+ }else{
+ throw new Error("invalid value for XML localName");
+ }
+ },
+ /**
+ * @description get the length of this xml tree, return 1 always for XML.
+ * @access public
+ * @return int
+ */
+ length: function(){
+ return 1;
+ },
+ /**
+ * @description return a special attribute type child by param
+ * @access public
+ * @param p{String} if the p is '*', return all attributes
+ * @return XML | XMLList
+ * @see attributes
+ */
+ attribute: function(p){
+ var attributes = this._attributes,
+ i,
+ l,
+ item,
+ list = new XMLList();
+ for( i =0, l = attributes.length; i <l; i++){
+ item = attributes[i];
+ if(item._qname.localName == p || p == '*'){
+ list._addXML(item);
+ }
+ }
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return all attribute type child.
+ * @access public
+ * @return XML | XMLList
+ * @see attribute
+ */
+ attributes: function(){
+ return this.attribute('*');
+ },
+ /**
+ * @description create a text type XML node by the text parameter,
+ * if the text contains special characters, use CDATA tag.
+ * @access private
+ * @param text{String}
+ * @return XML
+ */
+ _createTextNode: function(text){
+ var el = new XML();
+ el._nodeKind = NodeKind.TEXT;
+ el._text = text;
+ el._useCDATA =/['"<>&]/.test(text);
+ return el;
+ },
+ /**
+ * @description append child to the children list
+ * @access public
+ * @param child{XML | XMLList | String} the child need to be add
+ * @return XML
+ * @see prependChild
+ */
+ appendChild: function(child){
+ var cc = child.constructor;
+ if(cc == XML){
+ child._parent = this;
+ this._children.push(child);
+ }else if(cc == XMLList){
+ child.each(function(item){
+ item._parent = this;
+ });
+ this._children = this._children.concat(child._list);
+ }else if(cc == String){
+ var c = this._createTextNode(child);
+ c._parent = this;
+ this._children.push(c);
+ }
+ return this;
+ },
+ /**
+ * @description prepend child to the children list
+ * @access public
+ * @param child{XML | XMLList | String} the child need to be add
+ * @return XML
+ * @see appendChild
+ */
+ prependChild: function(child){
+ var cc = child.constructor;
+ if(cc == XML){
+ child._parent = this;
+ this._children.unshift(child);
+ }else if(cc == XMLList){
+ child.each(function(item){
+ item._parent = this;
+ });
+ this._children = this._list.concat(this._children);
+ }else if(cc === String){
+ var c = this._createTextNode(child);
+ c._parent = this;
+ this._children.unshift(c);
+ }
+ return this;
+ },
+ /**
+ * @description merge multi text childs nearby to one text child.
+ * @access public
+ * @return void
+ */
+ normalize: function(){
+ var i,
+ l,
+ preTextEl,
+ _c = this._children,
+ newChildren = [];
+
+ for(i = 0, l = _c.length; i < l; i++){
+ var item = _c[i],
+ nk = item.nodeKind();
+ if(nk == NodeKind.TEXT){
+ if(preTextEl){
+ item._text = preTextEl._text + item._text;
+ _c[i-1] = null;
+ }
+ preTextEl = item;
+ }else if(nk == NodeKind.ELEMENT){
+ item.normalize();
+ preTextEl = null;
+ }
+ }
+ for(i = 0, l = _c.length; i < l; i++){
+ _c[i] && newChildren.push(_c[i]);
+ }
+ this._children = newChildren;
+ },
+ /**
+ * @description return a filter children list, if the ignoreComments is true, the list will
+ * not contains any comment child, same as processing-instructions child.
+ * @access private
+ * @return Array
+ */
+ _getFilterChildren: function(){
+ var i,
+ l,
+ c = [],
+ _c = this._children;
+
+ for(i = 0, l = _c.length; i < l; i++){
+ var item = _c[i],
+ nk = item.nodeKind();
+ if(nk == NodeKind.ELEMENT || nk == NodeKind.TEXT ||
+ (nk == NodeKind.COMMENT && !XML.ignoreComments) ||
+ (nk == NodeKind.PROCESSING_INSTRUCTIONS && !XML.ignoreProcessingInstructions)){
+ c.push(item);
+ }
+ }
+ return c;
+ },
+ /**
+ * @description find a child by localName
+ * @access public
+ * @param p{String} the child localName, if the localName is '*', return all the child.
+ * @return XML | XMLList
+ */
+ child: function(p){
+ var list = new XMLList(),
+ i,
+ l,
+ c = this._getFilterChildren();
+ if(typeof p == 'number'){
+ if(c.length != 0 && c[p]){
+ list._addXML(c[p]);
+ }
+ }else{
+ for(i=0, l=c.length; i < l;i++){
+ var xml = c[i];
+ if(xml.localName() == p || p=="*"){
+ list._addXML(xml);
+ }
+ }
+ }
+
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return the child index in its parent child list, return -1 if it is a root XML.
+ * @access public
+ * @return int
+ */
+ childIndex: function(p){
+ if(this._parent){
+ return arrayIndexOf(this._parent._getFilterChildren(), this);
+ }
+ return -1;
+ },
+ /**
+ * @description return all the child
+ * @access public
+ * @return XML | XMLList
+ */
+ children: function(){
+ return this.child("*");
+ },
+ /**
+ * @description set the child content
+ * @access public
+ * @param child{string | XML | XMLList} the child need to be replaced
+ * @return XML
+ */
+ setChildren: function(child){
+ this._children = [];
+ return this.appendChild(child);
+ },
+ /**
+ * @description replace a child by new content.
+ * @access public
+ * @param a{string} the child need to be replaced
+ * @param b{String | XML | XMLList} the new content
+ * @return XML
+ */
+ replace: function(a, b){
+ var replacedIndex = -1,
+ i,
+ l,
+ c = this._children,
+ newChildren = [];
+
+ for(i=0, l=c.length; i < l; i++){
+ var xml = c[i], nk = xml.nodeKind();
+ if((xml.localName() == a || a=="*") && nk == NodeKind.ELEMENT){
+ if(replacedIndex == -1){
+ replacedIndex = i;
+ var cc = b.constructor;
+ if(cc == XML){
+ b._parent = this;
+ newChildren.push(b);
+ }else if(cc == XMLList){
+ b.each(function(item){
+ item._parent= this;
+ });
+ newChildren = newChildren.concat(b._list);
+ }else if(cc === String){
+ var t= this._createTextNode(b);
+ t._parent = this;
+ newChildren.push(t);
+ }
+ }
+ }else{
+ newChildren.push(xml);
+ }
+ }
+ if(replacedIndex != -1){
+ this._children = newChildren;
+ this.normalize();
+ }
+ return this;
+ },
+ /**
+ * @description find element type child.
+ * @access public
+ * @param p{String} the child localName, if the localName is '*', return all the element type child.
+ * @return XML | XMLList
+ */
+ elements: function(p){
+ if(arguments.length == 0){
+ p = '*';
+ }
+ var list = new XMLList(),
+ i,
+ l,
+ c = this._children;
+
+ for(i=0, l=c.length; i < l;i++){
+ var xml = c[i];
+ if((xml.localName() == p || p=='*') && xml.nodeKind() == NodeKind.ELEMENT){
+ list._addXML(xml);
+ }
+ }
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description find descendants child from the XML tree top.
+ * @access public
+ * @param p{String} the descendant localName, if the localName is '*', return all the descendants.
+ * @return XML | XMLList
+ */
+ descendants: function(p){
+ if(arguments.length == 0){
+ p = '*';
+ }
+ var list = new XMLList(),
+ i,
+ l,
+ c = this._children;
+
+ for(i=0, l=c.length; i < l;i++){
+ var xml = c[i], nk = xml.nodeKind();
+ if((xml.localName() == p || p=='*') && (nk==NodeKind.ELEMENT || nk == NodeKind.TEXT)){
+ list._addXML(xml);
+ }
+ if(xml._nodeKind == NodeKind.ELEMENT){
+ list._addXML(xml.descendants(p));
+ }
+ }
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description insert a child after the special child.
+ * @access public
+ * @param child1{XML | XMLList} the child in XML
+ * @param child2{XML | XMLList} the child need to be inserted.
+ * @return XML
+ * @see insertChildAfter
+ */
+ insertChildBefore: function(child1, child2){
+ if(child1 == null){
+ return this.appendChild(child2);
+ }
+ if(child1.constructor != XML){
+ return undefined;
+ }
+ var cc = child1.childIndex();
+ if(child1._parent == this && cc != -1){
+ if(child2.constructor == XML){
+ child2._parent = this;
+ this._children.splice(cc, 0, child2);
+ }else if(child2.constructor == XMLList){
+ for(var i = 0, l = child2._list.length; i < l; i++){
+ child2._list[i]._parent = this;
+ this._children.splice(cc+i, 0, child2._list[i]);
+ }
+ }else{
+ return undefined;
+ }
+ return this;
+ }else{
+ return undefined;
+ }
+ },
+ /**
+ * @description insert a child before the special child.
+ * @access public
+ * @param child1{XML | XMLList} the child in XML
+ * @param child2{XML | XMLList} the child need to be inserted.
+ * @return XML
+ * @see insertChildBefore
+ */
+ insertChildAfter: function(child1, child2){
+ if(child1 == null){
+ return this.prependChild(child2);
+ }
+ if(child1.constructor != XML){
+ return undefined;
+ }
+ var cc = child1.childIndex();
+ if(child1._parent == this && cc != -1){
+ if(child2.constructor == XML){
+ child2._parent = this;
+ this._children.splice(cc+1, 0, child2);
+ }else if(child2.constructor == XMLList){
+ for(var i = 0, l = child2._list.length; i < l; i++){
+ child2._list[i]._parent = this;
+ this._children.splice(cc+1+i, 0, child2._list[i]);
+ }
+ }else{
+ return undefined;
+ }
+ return this;
+ }else{
+ return undefined;
+ }
+ },
+ /**
+ * @description return the parent XML.
+ * @access public
+ * @return XML
+ */
+ parent: function(){
+ return this._parent;
+ },
+ /**
+ * @description check if the XML contains element type child, If has return false.
+ * @acess public
+ * @return Boolean
+ * @see hasComplexContent
+ */
+ hasSimpleContent: function(){
+ var c = this._children;
+ for(var i=0, l = c.length; i<l; i++){
+ var nk = c[i].nodeKind();
+ if(nk === NodeKind.ELEMENT){
+ return false;
+ }
+ }
+ return true;
+ },
+ /**
+ * @description check if the XML contains element type child, If has return true.
+ * @access public
+ * @return Boolean
+ * @see hasSimpleContent
+ */
+ hasComplexContent: function(){
+ return !this.hasSimpleContent();
+ },
+ /**
+ * @description return the comment type child
+ * @access public
+ * @return XML | XMLList
+ */
+ comments: function(){
+ var list = new XMLList(),
+ i,
+ l,
+ c = this._getFilterChildren();
+
+ for(i=0, l=c.length; i < l;i++){
+ var xml = c[i];
+ if(xml.nodeKind() == NodeKind.COMMENT){
+ list._addXML(xml);
+ }
+ }
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return the text type child
+ * @access public
+ * @return XML
+ */
+ text: function(){
+ var c = this._children,
+ r = "";
+ for(var i=0, l = c.length; i<l; i++){
+ var nk = c[i].nodeKind();
+ if(nk === NodeKind.TEXT){
+ if(c[i]._useCDATA){
+ r += c[i]._text;
+ }else{
+ r += replaceFromEntity(c[i]._text);
+ }
+ }
+ }
+ return this._createTextNode(r);
+ },
+ /**
+ * @description return the XML comments.
+ * @access public
+ * @return XMLList | XML
+ */
+ comments: function(){
+ var list = new XMLList(),
+ i,
+ l,
+ c = this._getFilterChildren();
+
+ for(i=0, l=c.length; i < l;i++){
+
+ var xml = c[i];
+ if(xml.nodeKind && xml.nodeKind() == NodeKind.COMMENT){
+ list._addXML(xml);
+ }
+ }
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return the XML processing-instructions.
+ * @access public
+ * @return XMLList | XML
+ */
+ processingInstructions: function(){
+ var list = new XMLList(),
+ i,
+ l,
+ c = this._getFilterChildren();
+
+ for(i=0, l=c.length; i < l;i++){
+
+ var xml = c[i];
+ if(xml.nodeKind && xml.nodeKind() == NodeKind.PROCESSING_INSTRUCTIONS){
+ list._addXML(xml);
+ }
+ }
+ return _getXMLIfLengthEqualOne(list);
+ },
+ /**
+ * @description return an XML copy
+ * @access public
+ * @return XML
+ */
+ copy: function(){
+ var xml = new XML(),
+ i,
+ l;
+ xml._nodeKind = this._nodeKind;
+ xml._text = this._text;
+ xml._useCDATA = this._useCDATA;
+ if(this._qname){
+ xml._qname = this._qname.copy();
+ }
+ for(i=0, l = this._namespaces.length; i < l; i++){
+ xml._namespaces[i] = this._namespaces[i].copy();
+ }
+ for(i = 0, l = this._attributes.length; i <l; i++){
+ xml._attributes[i] = this._attributes[i].copy();
+ }
+ for(i = 0, l = this._children.length; i <l; i++){
+ xml._children[i] = this._children[i].copy();
+ }
+ return xml;
+ },
+ /**
+ * @description format the XML to a String
+ * @param indent{int} the whitespace indent
+ * @access private
+ */
+ _toXMLString: function(indent, scopeNamespace){
+ var s = "",
+ tag,
+ i,
+ l,
+ nk = this._nodeKind,
+ ns = scopeNamespace ? this.inScopeNamespaces() : this._namespaces,
+ attrs = this._attributes,
+ children = this._children,
+ prettyPrinting = XML.prettyPrinting,
+ p = [];
+ indent = indent || 0;
+
+ if(prettyPrinting){
+ for(i = 0; i< indent; i++){
+ s +=" ";
+ }
+ }
+ if(nk == NodeKind.ATTRIBUTE){
+ return s + this._text;
+ }else if(nk == NodeKind.TEXT){
+ if(this._useCDATA){
+ return s + "<![CDATA["+this._text+"]]>";
+ }else{
+ return s + replaceToEntity(this._text);
+ }
+ }else if(nk == NodeKind.COMMENT){
+ return s + "<!--"+this._text +"-->";
+ }else if(nk == NodeKind.PROCESSING_INSTRUCTIONS){
+ return s + "<?" + this._text + "?>";
+ }
+
+ if(this._qname._ns.prefix){
+ tag = this._qname._ns.prefix+":" +this.localName();
+ }else{
+ tag = this.localName();
+ }
+
+ s += "<"+tag;
+ for(i = 0, l = ns.length; i <l; i++){
+ var prefix = ns[i].prefix ? 'xmlns:'+ns[i].prefix : 'xmlns';
+ p.push({label: prefix, value:ns[i].uri});
+ }
+ for(i = 0, l = attrs.length; i <l; i++){
+ var q = attrs[i]._qname,
+ prefix = q._ns.prefix,
+ label;
+ if(prefix){
+ label =prefix+ ':'+q.localName;
+ }else{
+ label = q.localName;
+ }
+ p.push({label:label, value:attrs[i]._text});
+ }
+ if(p.length>0){
+ for(i=0, l=p.length; i<l; i++){
+ s += " "+p[i].label+"=\""+p[i].value+"\"";
+ }
+ }
+ p = [];
+ for(i = 0, l = children.length; i < l; i++){
+ var el = children[i];
+ if(el.nodeKind() == NodeKind.ELEMENT){
+ p.push(el);
+ }else if(el.nodeKind() == NodeKind.COMMENT && !XML.ignoreComments){
+ p.push(el);
+ }else if(el.nodeKind() == NodeKind.PROCESSING_INSTRUCTIONS && !XML.ignoreProcessingInstructions){
+ p.push(el);
+ }else if(el.nodeKind() == NodeKind.TEXT){
+ p.push(el);
+ }
+ }
+ if(p.length == 0){
+ s += "/>";
+ }else if(p.length == 1 && p[0].nodeKind() == NodeKind.TEXT){
+ s += ">";
+ s += p[0]._toXMLString(0);
+ s += "</"+tag+">";
+ }else{
+ s += ">";
+ for(i = 0, l= p.length; i<l; i++){
+ if(prettyPrinting){
+ s += "\n";
+ }
+ s += p[i]._toXMLString(indent+XML.prettyIndent);
+ }
+ if(prettyPrinting){
+ s += "\n";
+ for(i = 0; i< indent; i++){
+ s += " ";
+ }
+ }
+ s += "</"+tag+">";
+ }
+ return s;
+ },
+ /**
+ * @description return the XML string
+ * @access public
+ * @return String
+ */
+ toXMLString: function(){
+ return this._toXMLString(0, true);
+ },
+ /**
+ * @description return a string representation. If it contains complex content, return the toXMLString.
+ * @access public
+ * @return String
+ */
+ toString: function(){
+ if(this.hasComplexContent()){
+ return this.toXMLString();
+ }
+ if(this.nodeKind() == NodeKind.TEXT || this.nodeKind() == NodeKind.ATTRIBUTE){
+ return this._text;
+ }
+ var s = "";
+ for(var i = 0, l = this._children.length; i < l; i++){
+ var el = this._children[i];
+ if(el._nodeKind == NodeKind.TEXT){
+ if(el._useCDATA){
+ s += el._text;
+ }else{
+ s += replaceFromEntity(el._text);
+ }
+ }
+ }
+ return s;
+ },
+ //================extension for javascript=========================
+ /**
+ * @description get the XML simple node value
+ * @access public
+ * @return String
+ * @see setValue
+ */
+ getValue: function(){
+ var nk = this._nodeKind;
+ if(nk == NodeKind.TEXT){
+ if(!this._useCDATA && containsEntity(this._text)){
+ return replaceFromEntity(this._text);
+ }
+ return this._text;
+ }else if(nk == NodeKind.ATTRIBUTE){
+ return this._text;
+ }else if(nk == NodeKind.ELEMENT && this.hasSimpleContent()){
+ var t = this.text();
+ if(t.getValue){
+ return t.getValue();
+ }
+ }
+ return undefined;
+ },
+ /**
+ * @description set the XML simple node value
+ * @access public
+ * @param val{String} the new node value
+ * @return void
+ * @see getValue
+ */
+ setValue: function(val){
+ var nk = this._nodeKind;
+ if(nk == NodeKind.TEXT || nk == NodeKind.ATTRIBUTE
+ || nk == NodeKind.COMMENT || nk == NodeKind.PROCESSING_INSTRUCTIONS){
+ this._text = val;
+ }else if(nk == NodeKind.ELEMENT && this.hasSimpleContent()){
+ var c = [],
+ newText = this._createTextNode(val);
+ newText._parent = this;
+ c.push(newText);
+ for(var i = 0, l = this._children.length; i < l; i++){
+ var item = this._children[i];
+ if(item._nodeKind != NodeKind.TEXT){
+ c.push(item);
+ }
+ }
+ this._children = c;
+ }
+ return this;
+ }
+ });
- //static properties
- XML.ingoreComments = true;
- XML.ignoreProcessingInstructions = true;
- XML.ignoreWhitespace = true;
- XML.prettyIndent = 2;
- XML.prettyPrinting = true;
+
+ /**
+ * @description static properties and methods.
+ */
+ merge(XML, {
+
+ ignoreComments: true,
+ ignoreProcessingInstructions: true,
+ ignoreWhitespace: true,
+ prettyIndent: 2,
+ prettyPrinting: true,
+
+ /**
+ * @description get an object copy indicating the XML setting.
+ * @return Object
+ */
+ settings: function(){
+ return {
+ ignoreComments: this.ignoreComments,
+ ignoreProcessingInstructions: this.ignoreProcessingInstructions,
+ ignoreWhitespace: this.ignoreWhitespace,
+ prettyIndent: this.prettyIndent,
+ prettyPrinting: this.prettyPrinting
+ }
+ },
+ /**
+ * @description set the XML setting
+ * @param sett{Object}
+ * @return void
+ */
+ setSettings: function(sett){
+ if(!sett){ return }
+ var assign = function(p){
+ if(sett.hasOwnProperty(p)){
+ XML[p] = sett[p];
+ }
+ }
+ assign("ignoreComments");
+ assign("ignoreProcessingInstructions");
+ assign("ignoreWhitespace");
+ assign("prettyIndent");
+ assign("prettyPrinting");
+ }
+ });
- //return global object jsxml
+ /**
+ * @description return global object jsxml
+ * @return Object
+ */
return {
+ containsEntity: containsEntity,
+ replaceToEntity: replaceToEntity,
+ replaceFromEntity: replaceFromEntity,
parseXML: _parseXML,
Namespace: Namespace,
QName: QName,
NodeKind: NodeKind,
+ XMLList: XMLList,
XML: XML
}
})();
View
758 tests/jsxml-test.js
@@ -6,10 +6,9 @@ YUI().use('test', function(Y){
XMLList = jsxml.XMLList,
QName = jsxml.QName,
NodeKind = jsxml.NodeKind,
- XMLNode = jsxml.XMLNode,
Namespace = jsxml.Namespace,
example = "<?xml version='1.0' encoding='utf-8'?>"
- +"<xml>sss"
+ +"<xml xmlns='uri' xmlns:h='h'>sss"
+"<a>a"
+"<e>e</e>"
+"<? instruction ?>"
@@ -56,6 +55,18 @@ YUI().use('test', function(Y){
qn = new QName(new Namespace("prefix", "http://uri"), "localName");
Assert.areEqual(qn.toString(), "http://uri::localName");
+ },
+ testCopy: function(){
+ var qn = new QName("uri", "localName");
+ var qn2 = qn.copy();
+ Assert.areEqual(qn2.toString(), "uri::localName");
+ },
+ testEquals: function(){
+ var qn = new QName("uri", "localName");
+ var qn2 = qn.copy();
+ Assert.isTrue(qn.equals(qn2));
+ qn2 = new QName("uri", "localName");
+ Assert.isTrue(qn.equals(qn2));
}
});
//NodeKind TestCase
@@ -67,7 +78,7 @@ YUI().use('test', function(Y){
testValue: function(){
Assert.areEqual(NodeKind.ELEMENT, 'element');
Assert.areEqual(NodeKind.COMMENT, 'comment');
- Assert.areEqual(NodeKind.PROCESSING_INSTRUCTION, 'processing-instruction');
+ Assert.areEqual(NodeKind.PROCESSING_INSTRUCTIONS, 'processing-instructions');
Assert.areEqual(NodeKind.TEXT, 'text');
Assert.areEqual(NodeKind.ATTRIBUTE, 'attribute');
}
@@ -109,15 +120,188 @@ YUI().use('test', function(Y){
testToString: function(){
var ns = new Namespace();
Assert.areEqual(ns.uri, ns.toString());
+ },
+ testCopy: function(){
+ var ns = new Namespace("prefix", "http://uri");
+ var ns2 = ns.copy();
+ Assert.areEqual(ns2.prefix, "prefix");
+ Assert.areEqual(ns2.uri, "http://uri");
+ },
+ testEquals: function(){
+ var ns = new Namespace("prefix", "http://uri");
+ var ns2 = ns.copy();
+ Assert.isTrue(ns.equals(ns2));
+ qn2 = new Namespace("prefix", "http://uri");
+ Assert.isTrue(ns.equals(ns2));
}
});
- //XMLNode TestCase
- var xmlNodeTestCase = new Y.Test.Case({
- name: "jsxml.XMLNode TestCase",
+
+ //XMLList TestCase
+ var xmllistTestCase = new Y.Test.Case({
+ name: "jsxml.XMLList TestCase",
testConstructor: function(){
- Assert.isFunction(XMLNode);
- Assert.isTrue(XMLNode, (new XMLNode()).constructor);
+ Assert.isFunction(XMLList);
+ Assert.areEqual(XMLList, (new XMLList()).constructor);
+
+ var list = new XMLList();
+ Assert.isArray(list._list);
+ Assert.areEqual(list._list.length, 0);
+ },
+ test_addXML: function(){
+ var list = new XMLList();
+ var xml = new XML();
+ list._addXML(xml);
+ Assert.areEqual(list._list.length, 1);
+ Assert.areEqual(xml, list._list[0]);
+ },
+ testLength: function(){
+ var xml =new XML("<a><b></b><b><c></c></b></a>");
+ Assert.areEqual(2, xml.child('b').length());
+ Assert.areEqual(0, xml.child('c').length());
+ },
+
+ testChildren: function(){
+ var xml = new XML("<a><b>1</b><b>2</b></a>");
+ var list = xml.child('b');
+ Assert.areEqual("12", list.children().toString());
+ Assert.areEqual("1\n2", list.children().toXMLString());
+ },
+ testChild: function(){
+ var xml = new XML("<a><b><c>1</c></b><b><c>2</c></b><b>3</b></a>");
+ var list = xml.child('b');
+ var cList = list.child('c');
+ Assert.areEqual("12", cList.children().toString());
+ Assert.areEqual("1\n2", cList.children().toXMLString());
+ },
+ testElements: function(){
+ var xml = new XML("<a><b><c>1</c></b><b><c>2</c></b><b>3</b></a>");
+ var list = xml.child('b');
+ var cList = list.elements('c');
+ Assert.areEqual("12", cList.children().toString());
+ Assert.areEqual("1\n2", cList.children().toXMLString());
+ },
+ testDescendants: function(){
+ var xml = new XML("<a><b><d>1</d></b><b><c><d>2</d></c></b><b><d>3</d></b></a>");
+ var list = xml.child('b');
+ var dList = list.descendants('d');
+ Assert.areEqual("123", dList.children().toString());
+ Assert.areEqual("1\n2\n3", dList.children().toXMLString());
+ },
+ testAttribute: function(){
+ var xml = new XML("<a><b a='a1' b='b1'><d>1</d></b><b a='a2' b='b2'><c><d>2</d></c></b><b><d>3</d></b></a>");
+ var list = xml.child('b');
+ var attList = list.attribute('a');
+ Assert.areEqual(2, attList.length());
+ Assert.areEqual('a1', attList.item(0).getValue());
+ Assert.areEqual('a2', attList.item(1).getValue());
+ },
+ testAttributes: function(){
+ var xml = new XML("<a><b a='a1' b='b1'><d>1</d></b><b a='a2' b='b2'><c><d>2</d></c></b><b><d>3</d></b></a>");
+ var list = xml.child('b');
+ var attList = list.attributes();
+ Assert.areEqual(4, attList.length());
+ Assert.areEqual('a1', attList.item(0).getValue());
+ Assert.areEqual('b1', attList.item(1).getValue());
+ Assert.areEqual('a2', attList.item(2).getValue());
+ Assert.areEqual('b2', attList.item(3).getValue());
+ },
+ testNormalize: function(){
+ var xml =new XML("<a><b> </b><b> </b></a>");
+ var i1 = xml.child('b').item(0);
+ i1.appendChild("hello");
+ Assert.areEqual(1, xml.child('b').item(0)._children.length, 'after append "hello" the children length should be 1');
+ i1.appendChild(" world");
+ Assert.areEqual(2, xml.child('b').item(0)._children.length, 'after append "word" the children length should be 2');
+ xml.normalize();
+ Assert.areEqual(1, xml.child('b').item(0)._children.length, 'after normalize the children length should be 1');
+ },
+ testComments: function(){
+ XML.ignoreComments = false;
+ var xml = new XML("<a><!--0--><b>1<!--1--></b><b>2<!--2--></b><b><c><!--3--></c></b><c><!--4--></c></a>");
+ var c = xml.child('b').comments();
+ XML.ignoreComments = true;
+ Assert.areEqual("<!--1-->\n<!--2-->", c.toXMLString());
+ },
+ testText: function(){
+ var xml = new XML("<a>0<b>1</b><b>2</b><b><c>3</c></b><c>4</c></a>");
+ var list = xml.child('b');
+ var newList = list.text();
+ Assert.areEqual(2, newList.length());
+ Assert.areEqual("12", newList.toString());
+ },
+ testMethodProcessingInstructions: function(){
+ XML.ignoreProcessingInstructions = false;
+ var xml = new XML("<a><?0 ?><b>1<?1 ?></b><b>2<?2 ?></b><b><c><?3 ?></c></b><c><?4 ?></c></a>");
+ var pi = xml.child('b').processingInstructions();
+ XML.ignoreProcessingInstructions = true;
+ Assert.areEqual("<?1 ?>\n<?2 ?>", pi.toXMLString());
+ },
+ testHasSimpleContent: function(){
+ var xml = new XML('<a><b>1</b><b></b></a>');
+ var list = xml.child('b');
+ Assert.isTrue(list.hasSimpleContent());
+ },
+ testHasComplexContent: function(){
+ var xml = new XML('<a><b><c/></b><b/></a>');
+ var list = xml.child('b');
+ Assert.isTrue(list.hasComplexContent());
+ },
+ testToString: function(){
+ var xml = new XML("<a><b>1</b><b>2</b></a>");
+ var list = xml.child('b');
+ Assert.areEqual( "12", list.toString());
+ },
+ testToXMLString: function(){
+ var xml = new XML("<a><b>1</b><b>2</b></a>");
+ var list = xml.child('b');
+ Assert.areEqual("<b>1</b>\n<b>2</b>", list.toXMLString());
+
+ xml = new XML('<a><b><c/></b><b/></a>');
+ Assert.areEqual(2, xml._children.length, 'xml should has 2 child');
+ list = xml.child('b')
+ Assert.areEqual("<b>\n <c/>\n</b>\n<b/>", list.toXMLString());
+
+ xml = new XML("<a><b><c>1</c><c><d></d></c></b><b>2</b></a>");
+ list = xml.child('b');
+ Assert.areEqual(2, list.length());
+ Assert.areEqual(XMLList, list.constructor);
+ Assert.areEqual("<b>\n <c>1</c>\n <c>\n <d/>\n </c>\n</b>\n<b>2</b>", list.toXMLString());
+ },
+ testCopy: function(){
+ var xml = new XML('<xml><a></a><a></a><a b="1" c="2"><b></b><c><d></d></c></a></xml>');
+ var list = xml.child('a');
+ var listCopy = list.copy();
+ Assert.areEqual(list.toString(), listCopy.toString(), 'listCopy should has a same toString() value');
+ Assert.areEqual(list.toXMLString(), listCopy.toXMLString(), 'listCopy should has a same toXMLString() value');
+ },
+ //extension for javascript
+ testItem: function(){
+ var xml = new XML("<a><b>1</b><b>2</b></a>");
+ var item1 = xml.child('b').item(0);
+ var item2 = xml.child('b').item(1);
+ var item3 = xml.child('b').item(2);
+ Assert.areEqual("<b>1</b>", item1.toXMLString());
+ Assert.areEqual("<b>2</b>", item2.toXMLString());
+ Assert.isUndefined(item3, 'item3 shoud be undefined');
+ },
+ testEach: function(){
+ var count = 0;
+ var arr1 = [];
+ var arr2 = [];
+ var xml = new XML("<a><b>1</b><b>2</b></a>");
+ xml.child('b').each(function(item, index){
+ count++;
+ arr1.push(item);
+ arr2.push(index);
+ });
+ Assert.areEqual(2, count, 'the each function should execute 2 times');
+ Assert.areEqual(0, arr2[0]);
+ Assert.areEqual(1, arr2[1]);
+ Assert.areEqual('<b>1</b>', arr1[0].toXMLString());
+ Assert.areEqual('<b>2</b>', arr1[1].toXMLString());
+
}
+
});
//XML TestCase
var xmlTestCase = new Y.Test.Case({
@@ -128,9 +312,551 @@ YUI().use('test', function(Y){
testConstructor: function(){
Assert.isFunction(XML);
Assert.areEqual(XML, (new XML()).constructor);
+
+ var xml = new XML();
+ Assert.isArray(xml._attributes);
+ Assert.isArray(xml._children);
+ Assert.isNull(xml._parent);
+ Assert.areEqual(NodeKind.ELEMENT, xml._nodeKind);
+ },
+ testNodeKind: function(){
+ var list = new XML();
+ list._nodeKind = NodeKind.ATTRIBUTE;
+ Assert.areEqual(list.nodeKind(), NodeKind.ATTRIBUTE);
+ list._nodeKind = NodeKind.TEXT;
+ Assert.areEqual(list.nodeKind(), NodeKind.TEXT);
+ list._nodeKind = NodeKind.COMMENT;
+ Assert.areEqual(list.nodeKind(), NodeKind.COMMENT);
+ list._nodeKind = NodeKind.PROCESSING_INSTRUCTION;
+ Assert.areEqual(list.nodeKind(), NodeKind.PROCESSING_INSTRUCTION);
+ },
+ testLength: function(){
+ var xml = new XML();
+ Assert.areEqual(xml.length(), 1);
+ },
+ testName: function(){
+ var xml = new XML();
+ Assert.areEqual(xml.name(), null);
+ Assert.areEqual(xml.localName(), null);
+
+ var ns = new Namespace("prefix", "http://uri");
+ var qname = new QName(ns, "localName");
+ xml._qname = qname;
+ Assert.areEqual(xml.name(), "http://uri:localName");
+ Assert.areEqual(xml.localName(), "localName");
+
+ xml.setName("newName");
+ Assert.areEqual(xml.name(), "newName");
+ Assert.areEqual(xml.localName(), "newName");
+
+ qname = new QName(ns, "localName");
+ xml._qname = qname;
+ xml.setLocalName("newLocalName");
+ Assert.areEqual(xml.name(), "http://uri:newLocalName");
+ Assert.areEqual(xml.localName(), "newLocalName");
+
+ var faild = false;
+ try{
+ xml.setName("1");
+ }catch(e){ faild = true;};
+ Assert.isTrue(faild);
+
+ faild = false;
+ try{
+ xml.setName("a1");
+ }catch(e){ faild = true;};
+ Assert.isFalse(faild);
+
+ faild = false;
+ try{
+ xml.setName("a:1");
+ }catch(e){ faild = true;};
+ Assert.isTrue(faild);
+
+ false;
+ try{
+ xml.setLocalName("1");
+ }catch(e){ faild = true;};
+ Assert.isTrue(faild);
+
+ faild = false;
+ try{
+ xml.setLocalName("a1");
+ }catch(e){ faild = true;};
+ Assert.isFalse(faild);
+
+ faild = false;
+ try{
+ xml.setLocalName("a:1");
+ }catch(e){ faild = true;};
+ Assert.isTrue(faild);
+
+ },
+ testNamespaceDeclaration: function(){
+ var xml = new XML();
+ Assert.isArray(xml._namespaces);
+ Assert.areEqual(xml._namespaces.length, 0);
+ var ns = new Namespace("prefix", "uri");
+ xml._namespaces.push(ns);
+ var dArr = xml.namespaceDeclarations();
+ Assert.isArray(dArr);
+ Assert.areEqual(1, dArr.length);
+ Assert.areEqual(ns, dArr[0]);
+
+ xml = new XML("<a xmlns='uri' xmlns:a='a' xmlns:b='b'/>");
+ dArr = xml.namespaceDeclarations();
+ Assert.areEqual(3, dArr.length);
+ },
+ testAddNamespace: function(){
+ var xml = new XML();
+ var ns = new Namespace("prefix", "uri");
+ xml.addNamespace(ns);
+ Assert.areEqual(ns, xml._namespaces[0]);
+ },
+ testRemoveNamespace: function(){
+ var xml = new XML();
+ var ns = new Namespace("prefix", "uri");
+ xml.addNamespace(ns);
+ Assert.areEqual(ns, xml._namespaces[0]);
+ xml.removeNamespace(ns);
+ Assert.areEqual(0, xml._namespaces.length);
+ },
+ testNamespace: function(){
+ var xml = new XML();
+ var ns = new Namespace("prefix", "uri");
+ xml.addNamespace(ns);
+ var myNs = xml.namespace("prefix");
+ Assert.areEqual(ns, myNs);
+
+ var myNs2 = xml.namespace();
+ Assert.areEqual(myNs2.constructor, Namespace);
+
+ var myNs3 = xml.namespace("prefix2");
+ Assert.isUndefined(myNs3);
+
+ },
+ testSetNamespace: function(){
+ var xml = new XML();
+ var ns = new Namespace("prefix", "uri");
+ xml._qname = new QName();
+ xml.setNamespace(ns);
+ Assert.areEqual(xml._qname.uri, "uri");
+ },
+ testInScopeNamespaces: function(){
+ var xml =new XML("<a xmlns:ns='uri' xmlns:pns='p' p='1' b='2'><b>b</b><c>c</c></a>");
+ var b = xml.child('b');
+ var c = xml.child('c');
+ var bns = b.inScopeNamespaces();
+ var cns = c.inScopeNamespaces();
+ Assert.areEqual(2, bns.length, 'child b should be in 2 scope namespaces');
+ Assert.areEqual(2, cns.length, 'child c should be in 2 scope namespaces');
+ var ns1 = bns[0];
+ Assert.areEqual(Namespace, ns1.constructor, 'the item of inScopeNamespaces shoud be Namespace');
+ Assert.areEqual('uri', ns1.uri);
+ Assert.areEqual('ns', ns1.prefix);
+ var ns2 = bns[1];
+ Assert.areEqual('p', ns2.uri);
+ Assert.areEqual('pns', ns2.prefix);
+ },
+ testChildIndex: function(){
+ var xml = new XML();
+ Assert.areEqual(-1, xml.childIndex());
+
+ xml = new XML("<a><b>b</b><c>c</c></a>");
+ Assert.areEqual(XML, xml.child('b').constructor, 'the children b should be the XML');
+ Assert.areEqual(xml, xml.child('b')._parent, 'the children b\'s parent should be xml');
+ Assert.areEqual(xml._getFilterChildren()[0], xml.child('b'));
+ Assert.areEqual(0, xml.child('b').childIndex(), "the tag b should be the first tag");
+ Assert.areEqual(1, xml.child('c').childIndex(), "the tag c should be the second tag");
+
+ },
+ testAppendChild: function(){
+ var xml = new XML("<a></a>");
+ var child = new XML("<b></b>");
+ var f = new XML("<a><b></b></a>");
+ var result = xml.appendChild(child);
+ Assert.areEqual(xml._children.length, 1);
+ Assert.areEqual(xml._children[0], child);
+ Assert.areEqual(xml, result);
+ Assert.areEqual(f.toXMLString(), xml.toXMLString());
+
+ xml = new XML("<a><c></c></a>");
+ child = new XML("<b></b>");
+ f = new XML("<a><c></c><b></b></a>");
+ result = xml.appendChild(child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f.toXMLString(), xml.toString());
+ },
+ testPrependChild: function(){
+ var xml = new XML("<a></a>");
+ var child = new XML("<b></b>");
+ var f = new XML("<a><b></b></a>");
+ var result = xml.prependChild(child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f.toXMLString(), xml.toXMLString());
+
+ xml = new XML("<a><c></c></a>");
+ child = new XML("<b></b>");
+ f = new XML("<a><b></b><c></c></a>");
+ result = xml.prependChild(child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f.toXMLString(), xml.toString());
+ },
+ testNormalize: function(){
+ var xml = new XML("<a></a>");
+ xml.appendChild("hello");
+ Assert.areEqual(1, xml._children.length);
+ xml.appendChild(" world");
+ Assert.areEqual(2, xml._children.length);
+ xml.normalize();
+ Assert.areEqual(1, xml._children.length);
+
+ var f = new XML("<a>hello world</a>");
+ Assert.areEqual(f.toXMLString(), xml.toXMLString());
+ },
+ testChild: function(child){
+ var xml = new XML("<a><b>b</b><c>c</c><c>c2</c></a>");
+ Assert.areEqual(XML, xml.child('b').constructor);
+ Assert.areEqual(XMLList, xml.child('c').constructor);
+
+
+ XML.ignoreComments = true;
+ xml = new XML("<a><!--pre comments--><b>b</b><c>c</c><c>c2</c><?post ps ?></a>");
+ Assert.areEqual(3, xml._getFilterChildren().length);
+
+ XML.ignoreComments = false;
+ xml = new XML("<a><!--pre comments--><b>b</b><c>c</c><c>c2</c><?post ps ?></a>");
+ var newIndex = xml.child('b').childIndex();
+ XML.ignoreComments = true;
+ Assert.areEqual(1, newIndex);
+
+ xml = new XML("<a>1</a>");
+ Assert.areEqual('1', xml.children().toXMLString(), "xml' s toXMLString should be 1");
+ Assert.areEqual('1', xml.children().toString(), "xml' s toString should be 1");
+
+ },
+ testChildren: function(child){
+ var xml = new XML("<a><!--pre comments--><b>b</b><c>c</c><c>c2</c><?post ps ?></a>");
+ Assert.areEqual(3, xml.children().length());
+
+ XML.ignoreComments = false;
+ var l2 = xml.children().length();
+ XML.ignoreComments = true;
+ Assert.areEqual(4, l2);
+
+ XML.ignoreComments = false;
+ XML.ignoreProcessingInstructions = false;
+ var l3 = xml.children().length();
+ XML.ignoreComments = true;
+ XML.ignoreProcessingInstructions = true;
+ Assert.areEqual(5, l3);
+ },
+ testInsertChildBefore: function(){
+ var child = new XML("<b></b>");
+ var xml = new XML("<a><c></c><d></d></a>");
+ var f1 = new XML("<a><b></b><c></c><d></d></a>");
+ var f2 = new XML("<a><c></c><b></b><d></d></a>");
+ var f3 = new XML("<a><c></c><d></d><b></b></a>");
+
+ var result = xml.insertChildBefore(xml.child('c'), child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f1.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ result = xml.insertChildBefore(xml.child('d'), child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f2.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ child = new XML("<b><e></e><e></e></b>");
+ var f4 = new XML("<a><e></e><e></e><c></c><d></d></a>");
+ result = xml.insertChildBefore(xml.child('c'), child.child('e'));
+ Assert.areEqual(f4.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ child = new XML("<b></b>");
+ result = xml.insertChildBefore(null, child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f3.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ var xmlCopy = new XML("<a><c></c><d></d>what</a>");
+ result = xml.insertChildBefore(null, "what");
+ Assert.isNotUndefined(result, "result should not be undefined");
+ Assert.areEqual(xmlCopy.toXMLString(), xml.toXMLString());
+ },
+
+ testInsertChildAfter: function(){
+ var child = new XML("<b></b>");
+ var xml = new XML("<a><c></c><d></d></a>");
+ var f1 = new XML("<a><c></c><b></b><d></d></a>");
+ var f2 = new XML("<a><c></c><d></d><b></b></a>");
+ var f3 = new XML("<a><b></b><c></c><d></d></a>");
+ var result = xml.insertChildAfter(xml.child('c'), child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f1.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ result = xml.insertChildAfter(xml.child('d'), child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f2.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ child = new XML("<b><e></e><e></e></b>");
+ var f4 = new XML("<a><c></c><e></e><e></e><d></d></a>");
+ result = xml.insertChildAfter(xml.child('c'), child.child('e'));
+ Assert.isNotUndefined(result);
+ Assert.areEqual(f4.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ child = new XML("<b></b>");
+ result = xml.insertChildAfter(null, child);
+ Assert.areEqual(result, xml);
+ Assert.areEqual(f3.toXMLString(), result.toXMLString());
+
+ xml = new XML("<a><c></c><d></d></a>");
+ var xmlCopy = new XML("<a>what<c></c><d></d></a>");
+ result = xml.insertChildAfter(null, "what");
+ Assert.isNotUndefined(result, "result should not be undefined");
+ Assert.areEqual(xmlCopy.toXMLString(), xml.toXMLString())
+ },
+ testParent: function(){
+ var xml = new XML("<a><b></b></a>");
+ var child = xml.child('b');
+ Assert.areEqual(xml, child.parent());
+
+ xml = new XML("<a><b><c></c></b></a>");
+ var child1 = xml.child('b');
+ var child2 = child1.child('c');
+ Assert.areEqual(child1, child2.parent());
+ Assert.areEqual(xml, child1.parent())
+ },
+ testText: function(){
+ var xml = new XML("<a>1<b>2</b>3</a>");
+ Assert.areEqual("13", xml.text().toString());
+ },
+ testSetChildren: function(){
+ var xml = new XML("<a>a<b>b</b></a>");
+ xml.setChildren("new");
+ Assert.areEqual("<a>new</a>", xml.toXMLString());
+
+ xml.setChildren(new XML("<b>b</b>"));
+ Assert.areEqual("<a>\n <b>b</b>\n</a>", xml.toString());
+
+ var list = (new XML("<a><b>1</b><b>2</b></a>")).child("b");
+ xml.setChildren(list);
+ Assert.areEqual(2, list.length());
+ Assert.areEqual("<a>\n <b>1</b>\n <b>2</b>\n</a>", xml.toString());
+ },
+ testReplace: function(){
+ var xml = new XML("<a>before<b>b</b>after<b>b</b></a>");
+ xml.replace("b", "__replace__");
+ var compareXML = new XML("<a>before__replace__after</a>");
+ Assert.areEqual(compareXML.toXMLString(), xml.toXMLString());
+
+ },
+ testElements: function(){
+ var xml = new XML("<a>a<b>b</b><c>c</c><!--comments--><?ins ?></a>");
+ Assert.areEqual(2, xml.elements().length());
+ Assert.areEqual(1, xml.elements('c').length());
+ Assert.areEqual(0, xml.elements('d').length());
+ },
+ testDescendents: function(){
+ var xml =new XML( "<a><b>b<b>2</b></b><c><b>3</b></c></a>" );
+
+ var p = xml.child("null");
+ p._addXML(new XML("<b>b<b>2</b></b>"));
+ p._addXML(new XML("<b>2</b>"));
+ p._addXML(new XML("<b>3</b>"));
+ Assert.areEqual(p.toXMLString(), xml.descendants("b").toXMLString(), "b descendents shoud be equal:");
+
+ p = xml.child("null");
+ p._addXML(xml.child("b"));
+ p._addXML(xml.child("b").text());
+ p._addXML(xml.child("b").child("b"));
+ p._addXML(xml.child("b").child("b").text());
+ p._addXML(xml.child("c"));
+ p._addXML(xml.child("c").child("b"));
+ p._addXML(xml.child("c").child("b").text());
+ Assert.areEqual(p.toXMLString(), xml.descendants().toXMLString(), "* descendants should be equal");
+ },
+ testAttribute: function(){
+ var xml = new XML("<a b='1' c='2'/>");
+ var attr = xml.attribute('b');
+ Assert.areEqual(NodeKind.ATTRIBUTE, attr.nodeKind());
+ Assert.areEqual('1', attr._text, 'attr._text should be 1');
+ Assert.areEqual('1', attr.toString(), 'toString value should be 1');
+ Assert.areEqual('1', attr.toXMLString());
+ attr = xml.attribute('c');
+ Assert.areEqual('2', attr.toString());
+ Assert.areEqual('2', attr.toXMLString());
+ },
+ testAttributes: function(){
+ var xml = new XML("<a b='1' c='2'/>");
+ var attrs = xml.attributes();
+ Assert.areEqual(XMLList, attrs.constructor);
+ Assert.areEqual('12', attrs.toString());
+ Assert.areEqual('1\n2', attrs.toXMLString());
+ Assert.areEqual(2, attrs.length());
+ Assert.areEqual(0, attrs.children().length());
+ },
+ testComments: function(){
+ XML.ignoreComments = false;
+ var xml = new XML("<!--pre comments--><a><!--inner1--><!--inner2--><b><!--child inner--></b></a><!--post comments-->");
+ var s = xml.comments();
+ XML.ignoreComments = true;
+
+ Assert.areEqual(XMLList, s.constructor);
+ Assert.areEqual(2, s.length());
+
+ },
+ testHasSimpleContent: function(){
+ var xml = new XML("<a>hello, jsxml</a>");
+ Assert.isTrue(xml.hasSimpleContent());
+ Assert.isFalse(xml.hasComplexContent());
+
+ xml = new XML("<a>hello, jsxml<!--comments--><?instruction?></a>");
+ Assert.isTrue(xml.hasSimpleContent());
+ Assert.isFalse(xml.hasComplexContent());
+
+ xml = new XML("<a><b/></a>");
+ Assert.isFalse(xml.hasSimpleContent());
+ Assert.isTrue(xml.hasComplexContent());
+
+ xml = new XML("<a>hello, jsxml<b/></a>");
+ Assert.isFalse(xml.hasSimpleContent());
+ Assert.isTrue(xml.hasComplexContent());
+
+ },
+ testToXMLString: function(){
+ XML.ignoreComments = true;
+ XML.ignoreProcessingInstructions = true;
+
+ var xml = new XML("<a>hello, jsxml</a>");
+ Assert.areEqual("<a>hello, jsxml</a>", xml.toXMLString());
+
+ xml = new XML("<a><b>hello, jsxml</b></a>");
+ Assert.areEqual("<a>\n <b>hello, jsxml</b>\n</a>", xml.toXMLString());
+
+ xml = new XML("<a><b>hello, jsxml<!--comment--></b></a>");
+ Assert.areEqual("<a>\n <b>hello, jsxml</b>\n</a>", xml.toXMLString());
+
+ XML.prettyPrinting = false;
+ var xmlstr = xml.toXMLString();
+ XML.prettyPrinting = true;
+ Assert.areEqual("<a><b>hello, jsxml</b></a>", xmlstr);
+ Assert.areEqual("<a>\n <b>hello, jsxml</b>\n</a>", xml.toXMLString());
+
+
+ xml = new XML("<a><b>hello, jsxml<!--comment--><?instruction?></b></a>");
+ Assert.areEqual("<a>\n <b>hello, jsxml</b>\n</a>", xml.toXMLString());
+
+
+ XML.ignoreComments = false;
+ xml = new XML("<a><b>hello, jsxml<!--comment--></b></a>");
+ Assert.areEqual("<a>\n <b>\n hello, jsxml\n <!--comment-->\n </b>\n</a>", xml.toXMLString());
+ XML.ignoreComments = true;
+
+ XML.ignoreProcessingInstructions = false;
+ xml = new XML("<a><b>hello, jsxml<!--comment--><?instruction?></b></a>");
+ Assert.areEqual("<a>\n <b>\n hello, jsxml\n <?instruction?>\n </b>\n</a>", xml.toXMLString());
+ XML.ignoreProcessingInstructions = true;
+
+ xml = new XML("<a></a>");
+ xml.appendChild("hello");
+ Assert.areEqual(xml._children.length, 1);
+ Assert.areEqual('<a>hello</a>', xml.toXMLString());
+ xml.appendChild(",world");
+ Assert.areEqual(xml._children.length, 2);
+ Assert.areEqual(xml.toXMLString(), '<a>\n hello\n ,world\n</a>');
+
+ xml = new XML("<ns:a xmlns:ns=\"uri\" m=\"1\">has attribute</ns:a>");
+ Assert.areEqual("a", xml.localName());
+ Assert.areEqual("uri:a", xml.name());
+ Assert.areEqual("<ns:a xmlns:ns=\"uri\" m=\"1\">has attribute</ns:a>", xml.toXMLString());
+
+ },
+ testToString: function(){
+ var xml = new XML("<a>hello</a>");
+ Assert.areEqual("hello", xml.toString());
+
+ xml.appendChild(",jsxml");
+ Assert.areEqual("hello,jsxml", xml.toString());
+
+ xml = new XML("<a><b>hello, jsxml</b></a>");
+ Assert.areEqual("<a>\n <b>hello, jsxml</b>\n</a>", xml.toString());
+
+ XML.prettyPrinting = false;
+ var xmlstr = xml.toString();
+ XML.prettyPrinting = true;
+ Assert.areEqual("<a><b>hello, jsxml</b></a>", xmlstr);
+ Assert.areEqual("<a>\n <b>hello, jsxml</b>\n</a>", xml.toString());
+
+ },
+ testCopy: function(){
+ var xml = new XML('<a b="1" c="2"><b></b><c><d></d></c></a>');
+ var xmlCopy = xml.copy();
+ Assert.areEqual(xml.toString(), xmlCopy.toString(), 'xmlCopy should has a same toString() value');
+ Assert.areEqual(xml.toXMLString(), xmlCopy.toXMLString(), 'xmlCopy should has a same toXMLString() value');
+ },
+ /**
+ "<xml>sss"
+ +"<a>a"
+ +"<e>e</e>"
+ +"<? instruction ?>"
+ +"</a>"
+ +"<b>b</b>"
+ +"<c att='1'/>"
+ +"<p><![CDATA[inner tag: @#?&<>;'<p></p>]]></p>"
+ +"</xml>";
+ */
+ testExample: function(){
+ var xml = new XML(example);
+ Assert.areEqual("a", xml.child('a').text().getValue());
+ Assert.areEqual("e", xml.child('a').child('e').getValue());
+ Assert.areEqual("b", xml.child('b').getValue());
+ Assert.areEqual("1", xml.child('c').attribute('att').getValue());
+ Assert.areEqual("inner tag: @#?&<>;'<p></p>", xml.child('p').getValue());
+
+ xml.child('p').setChildren('<p></p>');
+ Assert.isTrue(xml.child('p').text()._useCDATA, 'should auto use CDATA tag for special characters');
+ xml.child('p').setChildren('ppppppp');
+ Assert.isFalse(xml.child('p').text()._useCDATA, 'should not use CDATA tag for normal characters');
+ },
+
+ testSetSettings: function(){
+
+ var sett = XML.settings();
+ Assert.isTrue(sett.ignoreComments);
+ Assert.isTrue(sett.ignoreProcessingInstructions);
+ Assert.isTrue(sett.ignoreWhitespace);
+ Assert.areEqual(2, sett.prettyIndent);
+ Assert.isTrue(sett.prettyPrinting);
+
+ sett.prettyIndex = 4;
+ Assert.areEqual(2, XML.settings().prettyIndent);
+
+ XML.setSettings({
+ ignoreComments: false,
+ ignoreProcessingInstructions: false,
+ ignoreWhitespace: false,
+ prettyIndent: 4,
+ });
+
+ Assert.isFalse(XML.ignoreComments);
+ Assert.isFalse(XML.ignoreProcessingInstructions);
+ Assert.isFalse(XML.ignoreWhitespace);
+ Assert.areEqual(4, XML.prettyIndent);
+ Assert.isTrue(XML.prettyPrinting);
+
+ XML.ignoreComments = true;
+ XML.ignoreProcessingInstructions = true;
+ XML.ignoreWhitespace = true;
+ XML.prettyIndent = 2;
+ XML.prettyPrinting = true;
},
testIgnoreComments: function(){
- Assert.isTrue(XML.ingoreComments);
+ Assert.isTrue(XML.ignoreComments);
},
testIgnoreProcessingInstructions: function(){
Assert.isTrue(XML.ignoreProcessingInstructions);
@@ -144,8 +870,16 @@ YUI().use('test', function(Y){
testPrettyPrinting: function(){
Assert.isTrue(XML.prettyPrinting);
},
- testAddNamespace: function(){
- var xml = new XML();
+ //extension for javascript
+ testGetValue: function(){
+ var xml = new XML("<a>xml</a>");
+ var val = xml.getValue();
+ Assert.areEqual('xml', val);
+ },
+ testSetValue: function(){
+ var xml = new XML("<a>xml</a>");
+ xml.setValue("new Value");
+ Assert.areEqual("new Value", xml.getValue());
}
});
@@ -154,7 +888,7 @@ YUI().use('test', function(Y){
Y.Test.Runner.add(qnameTestCase);
Y.Test.Runner.add(nodekindTestCase);
Y.Test.Runner.add(namespaceTestCase);
- Y.Test.Runner.add(xmlNodeTestCase);
+ Y.Test.Runner.add(xmllistTestCase);
Y.Test.Runner.add(xmlTestCase);
Y.Test.Runner.run();
Please sign in to comment.
Something went wrong with that request. Please try again.