Usort не полностью сортирует

Я пытаюсь отсортировать список узлов по алфавиту, прежде чем отображать их в SimpleXML. Я использую функцию usort, аналогичную указанной здесь:

Сортировка результатов, возвращаемых SimpleXML и Xpath в PHP

Вот мой код:

$xQuery = $xml->comiclist->comic;

function cmp ($a, $b) {
     return strcmp(
         $a->mainsection->series->sortname, 
         $b->mainsection->series->sortname
     ); 
}

usort($xQuery, "cmp");

foreach ($xQuery as $comic) :

Проблема в том, что это работает только частично. Большинство элементов сгруппированы правильно, но некоторые совершенно неуместны. Как видно из функции, каждый узел $ comic сортируется по его дочернему элементу «mainsection-> series-> sortname».

Вот пример порядка, который он генерирует:

<sortname>New Avengers: Illuminati, Vol. 2</sortname>
<sortname>New Avengers: Illuminati, Vol. 2</sortname>
<sortname>Nova</sortname>
<sortname>New X-Men</sortname>
<sortname>Nation X</sortname>
<sortname>Namor, The Sub-Mariner Annual</sortname>

Как видите, они расположены не в алфавитном порядке. Я что-то упускаю? Любая помощь приветствуется.


person Batfan    schedule 30.09.2012    source источник


Ответы (1)


Если быстро взглянуть на свой вопрос, похоже, что вы используете usort для объекта типа SimpleXMLElement. Однако функция предназначена для использования с массивом.

Вероятно, преобразование объекта (или, точнее, итератора, который он предлагает) в массив сначала должно решить вашу проблему.

Объяснение: В примере, который вы связали, используется функция xpath, которая уже возвращает array, здесь, в вашем примере, это не так.

Функция преобразования предлагаемого итератора в массив - iterator_to_array:

$array = iterator_to_array($xQuery, false);

usort($array, "cmp");

foreach ($array as $comic) ...
person hakre    schedule 30.09.2012
comment
Примечание. Для параметра $ use_keys необходимо установить значение false, иначе в массиве будет только одна запись. Мне этого не хватало. - person hakre; 01.10.2012
comment
Имеет смысл. Спасибо, что разъяснили это! - person Batfan; 01.10.2012
comment
Еще одна вещь: я использую запрос xpath прямо перед тем, как отображать данные, чтобы получить данные с предыдущего и следующего узлов. Это работает нормально, за исключением того, что, похоже, не используется этот новый порядок сортировки. Вы можете увидеть код здесь db.tt/J1ZOLeKN Есть мысли? - person Batfan; 01.10.2012
comment
Сортируется только массив, XML не сортируется. usort предназначен для сортировки массивов, а не для сортировки элементов SimpleXML. Однако вы можете удалить все элементы, а затем снова добавить их по порядку. Однако это пересекает границу, где использование DomDocument имеет больше смысла (вы можете конвертировать между SimpleXML и DomDocument, так что не бойтесь). Вы могли бы просто захотеть заново сгенерировать некоторую XML-строку mabye вместо этого? - person hakre; 01.10.2012
comment
Хм, хорошо. Могу ли я выполнить запрос xpath в массиве, чтобы получить эту информацию? - person Batfan; 01.10.2012
comment
Вы можете смотреть на основе индекса массива для предыдущего и следующего узла. Это полностью избавит вас от xpath и позволит работать с отсортированным массивом (массив индексируется с нуля, count($array) сообщит вам количество элементов). Это то, что вы ищете (извините, не понял, почему у вас снова был xpath)? - person hakre; 01.10.2012
comment
Я просто пытаюсь каждый раз получить определенное значение из предыдущего и следующего узлов. Я могу заставить его подсчитать все узлы $ comic, но как мне заставить его динамически определять, какой из них является текущим? Я предполагаю, что тогда я могу просто -1 для предыдущего и +1 для следующего. - person Batfan; 01.10.2012
comment
Да, поигрался с этим, но безуспешно. - person Batfan; 01.10.2012
comment
ты хочешь отсортировать а тут это отображение? stackoverflow.com/q/12659004/367456 - person hakre; 01.10.2012
comment
Да, в идеале я бы хотел этим заняться. Тем временем я придумал решение jquery, но, в конечном счете, я бы предпочел, чтобы оно выполнялось на стороне сервера. - person Batfan; 02.10.2012
comment
Есть ли способ сделать этот счет и для числовой сортировки? Например, текущий порядок: Новые Люди Икс1, Новые Люди Икс10, Новые Люди Икс2. Желаемый порядок: Новые Люди Икс1, Новые Люди Икс2, Новые Люди Икс10 - person Batfan; 03.10.2012
comment
natsort, ищи естественный порядок сортировки. - person hakre; 03.10.2012