XMLの属性でソートしたい(数値の場合)

Sponsored Link

SimpleXMLでXML読み込み

PHPでXMLファイルを読み込み等処理を行う場合「SimpleXML」モジュールを使った例がよくあります。

そして、XML要素の並び順を明確にするために「属性」を指定して記述するパターンの場合、並び順をソートする必要があります。

属性の値が想定通りに並べ替えできるように指定されていれば問題ありませんが、数値として指定したつもりが、実際にソートをする際に処理のやり方によっては想定外とならない場合も。

例えば以下のような場合

<Question No="1" />
<Question No="2" />
<Question No="11" />
<Question No="123" />
<Question No="1000" />

この「No」を「strcmp」関数を使って文字列としてソートしてしまうと、想定しない並び順となってしまいます。これは「strcmp」関数の戻り値の仕様のためです。

string1 が string2 よりも小さければ < 0 を、string1が string2よりも大きければ > 0 を、 等しければ 0 を返します。

https://www.php.net/manual/ja/function.strcmp.php

「strcmp」関数の説明を見ると上記のように記述されているため、数値の比較にも使用できるかと一瞬思えますが、これでは想定した結果とはなりません。

>strcmp(“2”, “1”)

1

>strcmp(“2”, “11”)

1

「2」と「1」を比較した際には問題ありませんが、「2」と「11」を比較した際にも同じ結果となってしまっています。

なので、属性の値が「数値」の場合には「数値」に変換して比較する必要があります。

ま、これはPHPやXMLに限った話ではありませんが。。。

数値比較に「strcmp」を使用すると想定しない場合がある。

Sponsored Link

数値で比較するための関数を作成

// 昇順
function sort_trees_asc($t1, $t2)
{
    if((int)$t1['No'] == (int)$t2['No']) return 0;
    return ((int)$t1['No'] > (int)$t2['No']) ? 1 : -1;
}

// 降順
function sort_trees_desc($t1, $t2)
{
    if((int)$t1['No'] == (int)$t2['No']) return 0;
    return ((int)$t1['No'] < (int)$t2['No']) ? 1 : -1;
}

「昇順」「降順」でソートするための関数を用意。戻り値としては「strcmp」と同じ結果になるように「0」「正」「負」の値が返るように。

Sponsored Link

usort関数でソート

ソートは「usort」関数で行います。

第一引数にはソートを行いたい配列を、第二引数には先ほど作成した「sort_tree_asc」「sort_tree_desc」関数を指定。

// 昇順の場合
usort($target_array, 'クラス名::sort_trees_asc');
// 降順の場合
usort($target_array, 'クラス名::sort_trees_desc');

これで、数値としてソートされます。

もちろん、属性の値が「ABC1」「AEE5」のような文字列形式の場合は、また別途対応する必要があるかと思います。それはまた別の記事で。

タイトルとURLをコピーしました