空欄ありsun集計

今週は、XPathの記述で、落とし穴を回避するTipsの紹介です。
XPathで数字の合計を計算するには、sum関数を使いますね。
ところが、下のような XML で sum(/data/item/price) を合計すると、NaNと表示されます。

sum(/data/item/price)の結果

これは、sum関数は、引数の集合の中に、数字以外が含まれていると、集計エラーになり、
NaN というオブジェクトを返すからです。

こんなときどうする

sum関数の集計対象から、/data/item/price のうち、数字でないものを外します。
まず、数字かどうかの判定には、number() 関数が使います。
number() 関数は、引数に数字でないものが渡されると、戻り値に NaN というオブジェクトを返します
ここで、「NaNという文字列」と表現せず、オブジェクトと表現したのは、'NaN' では、
比較ができないからです。

  1. number( '123' ) → 123
  2. number( '' ) → NaN
  3. number( 'abc' ) → NaN

そこで、sum( /data/item/price[ string( number(.) != 'NaN'] ) と記述すれば、priceに
数字が入力されているもののみが、集計対象となります。
ポイントは、string( number(.) ) と、string関数で、number関数を囲んでいるところです。
このようにすることで、NaNオブジェクトを 'NaN' という文字列と比較できるようになります。

応用編

ついでに、全体のうち、何件を集計したかも表示してみることにします。
XPathは長くなりますが、以下のように記述します。
concat( sum( /data/item/price[ string( number(.) ) != 'NaN']), ',集計数=', count(/data/item/price[ string( number(.) ) != 'NaN']), '/', count(/data/item/price) )

まとめ

sum関数の Tips というよりは、XPathで、数字か否かを判定する Tipsとなりました。