コピペメモ
今までの $X は evaluate を二回する問題があってダサいので、使い勝手をそのままにしつつ新しくして使いはじめました。
- type 指定を導入
- ECMAScript 側で受けとりたい型を指定する。 (Array, String...)
- XPathResult.BOOLEAN_TYPE とか指定するのはめんどいし覚えられない。
- type 指定なしの場合は UNORDERED_NODE_ITERATOR_TYPE をそのまま Array に変換してかえす
- たぶんこれでも殆どの場合は問題ないと思う
- ノード集合じゃない (number とか) ならそれぞれそのままかえす (いままでとおなじ)
- type 指定で Array を指定した場合は ORDERED_NODE_SNAPSHOT_TYPE を Array に変換してかえす
- UNORDERED なやつで特別問題がある場合つかう
あんまり type 指定するの好きじゃないので (めんどい) 基本的に指定しなくても問題ないように
(長いのでまだ変更するかも)
// $X(exp);
// $X(exp, context);
// $X(exp, type);
// $X(exp, context, type);
function $X (exp, context, type /* want type */) {
if (typeof context == "function") {
type = context;
context = null;
}
if (!context) context = document;
var exp = (context.ownerDocument || context).createExpression(exp, function (prefix) {
var o = document.createNSResolver(context).lookupNamespaceURI(prefix);
if (o) return o;
return (document.contentType == "application/xhtml+xml") ? "http://www.w3.org/1999/xhtml" : "";
});
switch (type) {
case String:
return exp.evaluate(
context,
XPathResult.STRING_TYPE,
null
).stringValue;
case Number:
return exp.evaluate(
context,
XPathResult.NUMBER_TYPE,
null
).numberValue;
case Boolean:
return exp.evaluate(
context,
XPathResult.BOOLEAN_TYPE,
null
).booleanValue;
case Array:
var result = exp.evaluate(
context,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
var ret = [];
for (var i = 0, len = result.snapshotLength; i < len; i++) {
ret.push(result.snapshotItem(i));
}
return ret;
case undefined:
var result = exp.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
// not ensure the order.
var ret = [];
var i = null;
while (i = result.iterateNext()) {
ret.push(i);
}
return ret;
}
}
return null;
default:
throw(TypeError("$X: specified type is not valid type."));
}
}