上記を参考に以下のようなものを書いてみた。
var xml_get_by_xpath = function ( dom, xpath )
{
//全て小文字でないとうまくいかない
xpath = xpath.toLowerCase()
//ドキュメントを解決する。
dom = dom.ownerDocument || dom
//xmlnsがあるときはxpathにプレフィックスをつける。
var xmlns = dom.documentElement.getAttribute( "xmlns" )
if( xmlns )
{
//階層ごとに分割
xpaths = xpath.split("[")
var items = xpaths[0].split("/")
var length = items.length
for( var index = 0; index < length; ++index )
{
if( items[index].length )
{
//擬似要素の最後に並ぶのがタグ名。
var paths = items[index].split("::")
//その前にプレフィックスを付加
if( -1 == paths[paths.length-1].indexOf( ":" ) )
paths[paths.length-1] = "xmlns:" + paths[paths.length-1]
//連結
items[index] = paths.join("::")
}
}
//連結
xpaths[0] = items.join("/")
xpath = xpaths.join("[")
}
//expressionを作成
var expression = dom.createExpression( xpath,
function( prefix )
{
//もしxmlnsのプレフィックスを持っていたら、さっき見つけたxmlnsを返す。
if( "xmlns" == prefix )
return xmlns
return dom.createNSResolver(dom.documentElement).lookupNamespaceURI(prefix);
}
);
//まず探す
var result = expression.evaluate(dom.documentElement, 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:
{
result = expression.evaluate(dom.documentElement, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var results = [];
var length = result.snapshotLength
for( var index = 0; index < length; index++ )
results.push( result.snapshotItem( index ) );
return results;
}
}
return null;
}