namespace を持つ XML を JavaScript でパースする

namespace を持つ XML を JavaScript でパースするときのメモです。

前回

概要

XML のパースには、下記のように evaluate を使用してパースします。

var xpathResult = document.evaluate( xpathExpression, contextNode, namespaceResolver, resultType, result );

namespace を持つ XML をパースするには、 namespaceResolver 部分に、 namespace の情報を渡す必要があります。渡す値としては、デフォルトの Namespace Resolver を使う場合と、独自に作成した Namespace Resolver を使う場合があります。
ちなみに、 namespace を持たない XML の場合は null を渡します。

デフォルトの Namespace Resolver を使う場合

あらかじめ Namespace Resolver を生成しておきます。

var nsResolver = document.createNSResolver( contextNode.ownerDocument == null ? contextNode.documentElement : contextNode.ownerDocument.documentElement );

生成した Namespace Resolver を、 evaluate に渡します。

var xpathResult = document.evaluate( xpathExpression, contextNode, nsResolver, resultType, result );

独自に作成した Namespace Resolver を使う場合

次のような XML をパースすることを考えます。

<?xml version="1.0" encoding="utf-8"?>
<cities version="1.0.0" xmlns="https://michimani.net/2018/namespace">
    <city pref="1" city="1">札幌</city>
    <city pref="1" city="2">函館</city>
    <city pref="1" city="3">小樽</city>
    <city pref="1" city="4">室蘭</city>
    <city pref="2" city="1">弘前</city>
    <city pref="2" city="2">青森</city>
    <city pref="2" city="3">八戸</city>
    <city pref="3" city="1">盛岡</city>
    <city pref="3" city="2">釜石</city>
    <city pref="3" city="3">宮古</city>
</cities>

あらかじめ次のような関数を定義しておきます。

function customNsResolver() {
    return 'https://michimani.net/2018/namespace';
}

そして、 evaluate でパースする際に namespaceResolver として、定義した関数を渡します。

var xpathResult = document.evaluate( xpathExpression, contextNode, customNsResolver, resultType, result );

namespace を複数使いたい場合

上のパターンでは使用する namespace は 1 つでしたが、複数使用したい場合は下記のように関数を定義します。

function customNsResolver(prefix) {
    var ns = {
        'ns1': 'https://michimani.net/2018/namespace1',
        'ns2': 'https://michimani.net/2018/namespace2'
    };
    return ns[prefix] || null;
}

prefix の値は、指定する XPath の文字列内で指定します。
例えば、 ns1 の namespace を使用する場合は下記のような XPath を指定します。

let xpath = '//ns1:city[@pref='2' and @city='3']';

参考

comments powered by Disqus