intra-mart ® 7.2 patch09 Client Side JavaScript

im_xpath.js

概要

XMLオブジェクトの生成や解析をサポートするメソッドを提供します。

サンプルコード

ImXPathオブジェクトを使用して、XMLドキュメントの作成と
データを取得する例を示します。
<html>
<head>
<script src="csjs/im_xpath.js"></script>
<script language="javascript">
	
	// ■1.次の構造のXMLを作成します
	// <root>
	//    <fruit-list>
	//       <fruit>りんご</fruit>
	//       <fruit>みかん</fruit>
	//    </fruit-list>
	//    <vegetable-list>
	//       <vegetable>にんじん</vegetable>
	//       <vegetable code="001">きゅうり</vegetable>
	//    </vegetable-list>
	// </root>
	
	// XMLドキュメントオブジェクトを生成する
	var doc = ImXPath.createXmlDocument();
	
	// ノードの追加
	ImXPath.add(doc, "/root/fruit-list/fruit", "りんご");
	ImXPath.add(doc, "/root/fruit-list/fruit", "みかん");

	ImXPath.add(doc, "/root/vegetable-list/vegetable", "にんじん");

	ImXPath.add(doc, "/root/vegetable-list/vegetable/@code", "001");
	ImXPath.replace(doc, "/root/vegetable-list/vegetable[@code=001]", "きゅうり");


	// ■2.作成されたXMLから値を検索する

	// 2.1.ノードオブジェクトで取得する
	var sampleNode1 = ImXPath.evaluate(doc, "/root/vegetable-list/vegetable[@code=001]", false, ImXPath.NODE);
	alert(sampleNode1.firstChild.nodeValue);	// "きゅうり"が表示される
	alert(sampleNode1.getAttribute("code"));	// "001"が表示される

	// 2.2.テキストノードを取得する
	var sampleValue2 = ImXPath.evaluate(doc, "/root/vegetable-list/vegetable[@code=001]/text()", false, ImXPath.STRING);
	alert(sampleValue2);	// "きゅうり"が表示される

	// 2.3.ノードの配列を取得する
	var sampleNodeArray3 = ImXPath.evaluate(doc, "/root/fruit-list/fruit", true, ImXPath.NODE);
	for (var i = 0; i < sampleNodeArray3.length; i++) {
		alert(sampleNodeArray3[i].firstChild.nodeValue);	// "りんご"、"みかん"の順に表示される
	}

	// 2.4.属性値の配列を取得する
	var sampleAttributeArray4 = ImXPath.evaluate(doc, "/root/vegetable-list/vegetable/@code", true, ImXPath.NUMBER);
	for (var i = 0; i < sampleAttributeArray4.length; i++) {
		alert(sampleAttributeArray4[i]);	// NaN、1 の順に表示される
	}


	// ■3.ノードの追加と更新をする
	
	// 3.1."vegetable"ノードのcode="001"のテキストノードの値を、"きゅうり"から"なす"に変更します
	ImXPath.add(doc, "/root/vegetable-list/vegetable[@code=001]/text()", "なす");
	alert(ImXPath.evaluate(doc, "/root/vegetable-list/vegetable[@code=001]/text()", false, ImXPath.STRING));	// "かぼちゃ"が表示される

	// 3.2.テキストノードに"キャベツ"を持つ、新しい"vegetable"ノードを追加します
	ImXPath.add(doc, "/root/vegetable-list/vegetable", "キャベツ");

	// 3.実行結果(docの中身)
	// <root>
	//    <fruit-list>
	//       <fruit>りんご</fruit>
	//       <fruit>みかん</fruit>
	//    </fruit-list>
	//    <vegetable-list>
	//       <vegetable>にんじん</vegetable>
	//       <vegetable code="001">なす</vegetable>
	//       <vegetable>キャベツ</vegetable>
	//    </vegetable-list>
	// </root>

	// ■4.ノードを削除する
	
	// 4.1."fruit-list"ノードを削除します
	var rs = ImXPath.remove(doc, "/root/fruit-list");

	// 4.実行結果(docの中身)
	// <root>
	//    <vegetable-list>
	//       <vegetable>にんじん</vegetable>
	//       <vegetable code="001">なす</vegetable>
	//       <vegetable>キャベツ</vegetable>
	//    </vegetable-list>
	// </root>
</script>
</head>
<body>
</body>
</html>
 


Version: 1.0

Author: INTRAMART


クラスの概要
ImXPath XMLオブジェクトの生成や解析をサポートするメソッドを提供します。

/**
 * XMLオブジェクトの生成や解析をサポートするメソッドを提供します。
 * @fileoverview XMLオブジェクトの生成や解析をサポートするメソッドを提供します。
 * <h3>サンプルコード</h3>
 * ImXPathオブジェクトを使用して、XMLドキュメントの作成と<br/>
 * データを取得する例を示します。<br/>
 * <pre>
&lt;html&gt;
&lt;head&gt;
&lt;script src="csjs/im_xpath.js"&gt;&lt;/script&gt;
&lt;script language="javascript"&gt;
	
	// ■1.次の構造のXMLを作成します
	// &lt;root&gt;
	//    &lt;fruit-list&gt;
	//       &lt;fruit&gt;りんご&lt;/fruit&gt;
	//       &lt;fruit&gt;みかん&lt;/fruit&gt;
	//    &lt;/fruit-list&gt;
	//    &lt;vegetable-list&gt;
	//       &lt;vegetable&gt;にんじん&lt;/vegetable&gt;
	//       &lt;vegetable code="001"&gt;きゅうり&lt;/vegetable&gt;
	//    &lt;/vegetable-list&gt;
	// &lt;/root&gt;
	
	// XMLドキュメントオブジェクトを生成する
	var doc = ImXPath.createXmlDocument();
	
	// ノードの追加
	ImXPath.add(doc, "/root/fruit-list/fruit", "りんご");
	ImXPath.add(doc, "/root/fruit-list/fruit", "みかん");

	ImXPath.add(doc, "/root/vegetable-list/vegetable", "にんじん");

	ImXPath.add(doc, "/root/vegetable-list/vegetable/&#64;code", "001");
	ImXPath.replace(doc, "/root/vegetable-list/vegetable[&#64;code=001]", "きゅうり");


	// ■2.作成されたXMLから値を検索する

	// 2.1.ノードオブジェクトで取得する
	var sampleNode1 = ImXPath.evaluate(doc, "/root/vegetable-list/vegetable[&#64;code=001]", false, ImXPath.NODE);
	alert(sampleNode1.firstChild.nodeValue);	// "きゅうり"が表示される
	alert(sampleNode1.getAttribute("code"));	// "001"が表示される

	// 2.2.テキストノードを取得する
	var sampleValue2 = ImXPath.evaluate(doc, "/root/vegetable-list/vegetable[&#64;code=001]/text()", false, ImXPath.STRING);
	alert(sampleValue2);	// "きゅうり"が表示される

	// 2.3.ノードの配列を取得する
	var sampleNodeArray3 = ImXPath.evaluate(doc, "/root/fruit-list/fruit", true, ImXPath.NODE);
	for (var i = 0; i &lt; sampleNodeArray3.length; i++) {
		alert(sampleNodeArray3[i].firstChild.nodeValue);	// "りんご"、"みかん"の順に表示される
	}

	// 2.4.属性値の配列を取得する
	var sampleAttributeArray4 = ImXPath.evaluate(doc, "/root/vegetable-list/vegetable/&#64;code", true, ImXPath.NUMBER);
	for (var i = 0; i &lt; sampleAttributeArray4.length; i++) {
		alert(sampleAttributeArray4[i]);	// NaN、1 の順に表示される
	}


	// ■3.ノードの追加と更新をする
	
	// 3.1."vegetable"ノードのcode="001"のテキストノードの値を、"きゅうり"から"なす"に変更します
	ImXPath.add(doc, "/root/vegetable-list/vegetable[&#64;code=001]/text()", "なす");
	alert(ImXPath.evaluate(doc, "/root/vegetable-list/vegetable[&#64;code=001]/text()", false, ImXPath.STRING));	// "かぼちゃ"が表示される

	// 3.2.テキストノードに"キャベツ"を持つ、新しい"vegetable"ノードを追加します
	ImXPath.add(doc, "/root/vegetable-list/vegetable", "キャベツ");

	// 3.実行結果(docの中身)
	// &lt;root&gt;
	//    &lt;fruit-list&gt;
	//       &lt;fruit&gt;りんご&lt;/fruit&gt;
	//       &lt;fruit&gt;みかん&lt;/fruit&gt;
	//    &lt;/fruit-list&gt;
	//    &lt;vegetable-list&gt;
	//       &lt;vegetable&gt;にんじん&lt;/vegetable&gt;
	//       &lt;vegetable code="001"&gt;なす&lt;/vegetable&gt;
	//       &lt;vegetable&gt;キャベツ&lt;/vegetable&gt;
	//    &lt;/vegetable-list&gt;
	// &lt;/root&gt;

	// ■4.ノードを削除する
	
	// 4.1."fruit-list"ノードを削除します
	var rs = ImXPath.remove(doc, "/root/fruit-list");

	// 4.実行結果(docの中身)
	// &lt;root&gt;
	//    &lt;vegetable-list&gt;
	//       &lt;vegetable&gt;にんじん&lt;/vegetable&gt;
	//       &lt;vegetable code="001"&gt;なす&lt;/vegetable&gt;
	//       &lt;vegetable&gt;キャベツ&lt;/vegetable&gt;
	//    &lt;/vegetable-list&gt;
	// &lt;/root&gt;
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;
 * </pre>
 * @class XMLオブジェクトの生成や解析をサポートするメソッドを提供します。<br/>
 * ImXPathオブジェクトの利用およびサンプルコードは
 * <a href="overview-summary-im_xpath.js.html">こちら</a> を参照してください。<br/>
 * 
 * <h3><a name="location_path_detail">ロケーションパスについて</a></h3>
 * ImXPathの各メソッドで指定可能な「ロケーションパス」で使用可能な構文は以下になります。<br/>
 * 以下の構文を"/"(半角スラッシュ)でつないだものがロケーションパスになります。
 *
 * <p/>
 * <table border="1">
 *    <tr>
 *       <th>構文</th><th>内容</th>
 *    </tr>
 *    <tr>
 *       <td><i>TagName</i></td><td><i>TagName</i>ノードが選択されます</td>
 *    </tr>
 *    <tr>
 *       <td>text()</td><td>1テキストノードが選択されます</td>
 *    </tr>
 *    <tr>
 *       <td>&#64;<i>name</i></td><td><i>name属性</i>が選択されます</td>
 *    </tr>
 *    <tr>
 *       <td><i>TagName</i>[1]</td><td><i>TagName</i>ノードのうち1番目の要素が選択されます</td>
 *    </tr>
 *    <tr>
 *       <td><i>TagName</i>[last()]</td><td><i>TagName</i>ノードのうち最後の要素が選択されます</td>
 *    </tr>
 *    <tr>
 *       <td><i>TagName</i>[&#64;<i>name</i>=<i>value</i>]</td><td><i>TagName</i>ノードのうち、
 *          <i>name</i>属性が<i>value</i>の要素が選択されます
 *       </td>
 *    </tr>
 * </table>
 * <br/>
 * 例)
 * rootノードの子要素sampleノードの内、id属性が"001"のノードのテキストノードを選択する例です。<br/>
 * /root/sample[&#64;id=001]/text()<br/>
 * @constructor
 * @version 1.0
 * @since 6.1
 * @author INTRAMART
 */
function ImXPath(){}

/**
 * @private
 * 内部配列
 */
ImXPath.tmpArray;

/**
 * 戻り値の型(ノード)
 * @final 
 * @type Number
 */
ImXPath.NODE = 1;

/**
 * 戻り値の型(文字列)
 * @final 
 * @type Number
 */
ImXPath.STRING = 2;

/**
 * 戻り値の型(数値)
 * @final 
 * @type Number
 */
ImXPath.NUMBER = 3;

/**
 * 戻り値の型(真偽値)
 * @final 
 * @type Number
 */
ImXPath.BOOLEAN = 4;

/**
 * 新しいXMLドキュメントを生成します。
 * @type Object
 * @return XMLドキュメント
 */
ImXPath.createXmlDocument = function() {
	try {
		return document.implementation.createDocument("", "", null);
	} catch(e) {
		
	}
	
	try {
		return new ActiveXObject("Msxml2.DOMDocument.3.0");
	} catch(e) {
		
	}
	
	try {
		return new ActiveXObject("Microsoft.XMLDOM");
	} catch(e) {
		
	}

	return null;
}
	
/**
 * XMLドキュメントオブジェクトから、<a href="#location_path_detail">ロケーションパス</a>
 * で選択された値を取得します。<br/>
 * 取得された値は、typeで指定された型で返却します。<br/>
 * @param {Object} doc 解析を行うXMLドキュメント
 * @param {String} path <a href="#location_path_detail">ロケーションパス</a>
 * @param {Boolean} isArray [option]返却値を配列で受け取るかどうか<br/><br/>
 * 選択された値が複数存在する場合に、配列で返すかどうかを指定します。<br/>
 * falseが指定され、かつ複数の値が選択された場合は最初の要素の値が返却されます。<br/>
 * 省略された場合は複数の値が選択された場合のみ、配列で返却されます。<br/><br/>
 * @param {Number} type [option]返却値の型<br/><br/>
 * 以下を指定できます。<br/>
 * <table border="1">
 *    <tr>
 *       <th>設定値</th><th>型</th><th>説明</th>
 *    </tr>
 *    <tr>
 *       <td>ImXPath.NODE</td><td>ノード</td><td>選択されたノードを返却します。<br/>
 *           <a href="#location_path_detail">ロケーションパス</a>で属性値が選択された場合は、その属性値を持つノードを返却します。<br/>
 *           typeの指定が省略された場合は、ノードで返されます。
 *       </td>
 *    </tr>
 *    <tr>
 *       <td>ImXPath.STRING</td><td>文字列</td><td>選択された値を文字列として返します。</td>
 *    </tr>
 *    <tr>
 *       <td>ImXPath.NUMBER</td><td>数値</td><td>選択された値を数値として返します。
 *           数値にできない値が選択された場合は、NaNを返します。</td>
 *    </tr>
 *    <tr>
 *       <td>ImXPath.BOOLEAN</td><td>真偽値</td><td>選択された値が"true"(大文字、小文字は区別しない)
 *           の場合はtrueを返します。それ以外の場合はfalseを返します。</td>
 *    </tr>
 * </table>
 * @type Object
 * @return 解析結果
 */
ImXPath.evaluate = function(doc, path, isArray, type) {
	
	var nodes = ImXPath.getNodesByKey(doc, path, false);
	var result;
	
	if (type == undefined || type == ImXPath.NODE) {
		result = nodes;
	} else {
		var lastSyntax = ImXPath.getLastSyntax(path);
		result = new Array();
		
		for(var i = 0; i < nodes.length; i++) {
			
			var node = nodes[i];
			var val;
		
			if (lastSyntax.attributeKey != undefined) {
				val = node.getAttribute(lastSyntax.attributeKey);
			} else if (node.nodeType == 3 && lastSyntax.funcKey == "text()") {
				val = node.nodeValue;
			} else {
				val = node;
			}
			
			switch (type) {
				case ImXPath.STRING:
					result.push(val);
				break;
				
				case ImXPath.NUMBER:
					result.push(parseFloat(val));
				break;
				
				case ImXPath.BOOLEAN:
					if (val == null || val == undefined) {
						result.push(false);
					} else if (val.toUpperCase() == "TRUE") {
						result.push(true);
					} else {
						result.push(false);
					}
				break;
			}
		}
	}
	
	// 返却
	if (isArray == undefined) {
		if (result.length == 1) {
			return result[0];
		} else {
			return result;
		}
	} else if (isArray == true) {
		return result;
	} else if (isArray == false) {
		return result[0];
	} else {
		return result;
	}
}
	
/**
 * XMLを解析して値を置き換えます。<br/>
 * 指定されたXMLドキュメント内で<a href="#location_path_detail">ロケーションパス</a>
 * の値が既に存在していた場合は、その値を置き換えます。<br/>
 * 存在しない場合は、新しくノードや属性を作成します。
 * @param {Object} doc XMLドキュメント
 * @param {String} path <a href="#location_path_detail">ロケーションパス</a>
 * @param {String} value 置き換える値
 */
ImXPath.replace = function(doc, path, value) {
	ImXPath.setData(doc, path, value, false);
}
	
/**
 * XMLを解析して値を追加します。<br/>
 * 指定されたXMLドキュメント内に<a href="#location_path_detail">ロケーションパス</a>
 * のノードが既に存在しているかどうかに関わらず、新しいノードを作成します。<br/>
 * <a href="#location_path_detail">ロケーションパス</a>で、属性値が選択された場合は値を置き換えます。
 * @param {Object} doc XMLドキュメント
 * @param {String} path <a href="#location_path_detail">ロケーションパス</a>
 * @param {String} value 追加する値
 */
ImXPath.add = function(doc, path, value) {
	ImXPath.setData(doc, path, value, true);
}

/**
 * XMLを解析して値やノードを削除します。
 * @param {Object} doc XMLドキュメント
 * @param {String} path <a href="#location_path_detail">ロケーションパス</a>
 * @type Boolean
 * @return 削除成功/失敗
 */
ImXPath.remove = function(doc, path) {
	var nodes = ImXPath.getNodesByKey(doc, path, false);
	var lastSyntax = ImXPath.getLastSyntax(path);
	var result = false;
	
	try {
		for (var i = 0; i < nodes.length; i++) {
			if (lastSyntax.attributeKey == undefined) {
				nodes[i].parentNode.removeChild(nodes[i]);
				result = true;
			} else {
				// 属性が指定されている場合
				nodes[i].removeAttribute(lastSyntax.attributeKey);
				result = true;
			}
		}
	} finally {
		return result;
	}
}
	
/**
 * XMLを解析して値をセットします。
 *@private
 */
ImXPath.setData = function(doc, path, value, mode) {
	
	var nodes = ImXPath.getNodesByKey(doc, path, true, mode);
	var lastSyntax = ImXPath.getLastSyntax(path);
	
	for (var i = 0; i < nodes.length; i++) {
	
		if (lastSyntax.attributeKey == undefined) {

			// 属性が指定されていない場合
			var targetNode;
			if (nodes[i].nodeType == 3) {
				// テキストノードの場合
				targetNode = nodes[i].parentNode;
				if (nodes[i].nodeValue == "") {
					targetNode.removeChild(nodes[i]);
				}
			} else {
				targetNode = nodes[i];
			}
			
			if (mode == false) {
				// replaceのとき
				while (true) {
					var child = targetNode.childNodes[0];
					if (child == undefined || child == null) {
						break;
					}
					targetNode.removeChild(child);
				}
			}
			
			var type = typeof(value);
			if (type == "string" || type == "number" || type == "boolean") {
				targetNode.appendChild(doc.createTextNode(String(value)));
			} else {
				targetNode.appendChild(value);
			}
			
		} else {
			// 属性が指定されている場合
			nodes[i].setAttribute(lastSyntax.attributeKey, String(value));
		}
	}
}
	
/**
 * 指定されたキーから、ノード名の配列を取得します
 * @private
 */
ImXPath.getKeys = function(path) {

	var keys = path.split("/");
	var lastSyntax = keys[keys.length - 1];
	
	if (keys[0] == "") {
		// 先頭に"/"が付いていた場合
		keys.shift();
	}
	
	if (lastSyntax.indexOf("@") == 0) {
		// 属性指定の場合は除く
		keys.pop();
	}

	return keys;
}

/**
 * 指定されたキーから最後の構文を取得します
 * @private
 */
ImXPath.getLastSyntax = function(path) {
	var keys = path.split("/");
	
	var result = new Object();
	var lastSyntax = keys[keys.length -1];
	
	if (lastSyntax.indexOf("@") == 0) {
		result.attributeKey = lastSyntax.split("@")[1];
	} else {
		result.funcKey = lastSyntax;
	}
	return result;
}
	
	
/**
 * 指定されたキーにマッチするノードの配列を取得します
 * @private
 */
ImXPath.getNodesByKey = function(doc, path, notExistNodeCreate, mode) {
		
	var nodes = doc.childNodes;
	
	/*  // 初期化  */
	ImXPath.tmpArray = new Array();
	/*  // 検索  */
	var arykeys = ImXPath.getKeys(path);
	
	ImXPath.searchNodes(doc, doc.firstChild, nodes, arykeys, 0, notExistNodeCreate, mode);
	return ImXPath.tmpArray;
}

/**
 * ノードを検索します
 * @private
 */
ImXPath.searchNodes = function(doc, parentNode, nodes, keys, count, notExistNodeCreate, mode) {
	var isTargetExist = false;
	var key = String(keys[count]);
	count++;
	
	var nodeName;
	var predicate;
	var attributeKey;
	var attributeValue;
	var indexValue;

	if (key.indexOf("[") != -1 && key.indexOf("]") != -1) {
		nodeName = key.split("[")[0];
		
		predicate = key.split("[")[1].split("]")[0];	// 述部取得
		
		if (predicate.indexOf("@") == 0 && predicate.indexOf("=") >= 1) {
			// 属性値指定の場合
			attributeKey = predicate.split("=")[0].split("@")[1];
			attributeValue = predicate.split("=")[1];
		} else if (!isNaN(predicate)) {
			indexValue = parseInt(predicate);
		} else if(predicate == "last()") {
			indexValue = nodes.length;
		} else {
			ImXPath.tmpArray = new Array();
			return;
		}
	} else {
		nodeName = key;
	}

	for(var k = 0; k < nodes.length; k++) {
		
		if (nodeName == "text()" && nodes[k].nodeType == 3) {
			ImXPath.tmpArray.push(nodes[k]);
			continue;
		}
		
		if(nodes[k].tagName == nodeName || "*" == nodeName) {
			
			isTargetExist = true;
			
			if (attributeKey != undefined) {
				if (nodes[k].getAttribute(attributeKey) != attributeValue) {
					continue;
				}
			}
			
			if (indexValue != undefined) {
				if (indexValue != k + 1) {
					continue;
				}
			}
			
			if (keys.length == count) {
				ImXPath.tmpArray.push(nodes[k]);
			} else {
				ImXPath.searchNodes(doc, nodes[k], nodes[k].childNodes, 
										keys, count, notExistNodeCreate, mode);
			}
		}
	}

	/*  // ノードが見つからなかった場合  */
	if ((isTargetExist == false && notExistNodeCreate == true) || 
		(mode == true && keys.length == count)) {

		if (predicate == undefined) {
			count--;
			ImXPath.tmpArray = new Array();
			ImXPath.createNewChildNode(doc, parentNode, keys, count);
		}
	}
}

/**
 * 新しいノードを作成します
 * @private
 */
ImXPath.createNewChildNode = function(doc, parentNode, keys, count) {
	
	var key = String(keys[count]);
	if(key == ""){ return }

	var newElement;
	if (key == "text()") {
		newElement = doc.createTextNode("");
	} else {
		newElement = doc.createElement(key);
	}
	
	if (parentNode == undefined || parentNode == null) {
		parentNode = doc;
	}
	
	parentNode.appendChild(newElement);
	count++;
	
	if (keys.length == count) {
		ImXPath.tmpArray.push(newElement);
	} else {
		ImXPath.createNewChildNode(doc, newElement, keys, count);
	}
}
	


intra-mart ® 7.2 patch09 Client Side JavaScript

このドキュメントはJSDoc によって Mon Dec 15 17:12:34 2014に作成されました。