Как извлечь и отсортировать данные многомерного массива с помощью PHP из файла XML (используя simpleXML) - PullRequest
0 голосов
/ 15 октября 2019

Надеюсь, вы можете помочь мне с моей проблемой ...

У меня есть этот XML-файл, который я получаю информацию с помощью функции simplexml_load_file():

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <Xiami>
    <ArtistID>179</ArtistID>
    <ArtistName>Band 1</ArtistName>
    <XiamiID>9dl4gN1c745</XiamiID>
    <Streaming>246</Streaming>
    <Fans>84</Fans>
    <TotalComments>1992</TotalComments>
      <AllSongs>
        <Songs>
          <SongID>8ILroS998dc</SongID>
          <SongName>Song 1</SongName>
          <SongComments>9223</SongComments>
        </Songs>
        <Songs>
          <SongID>8ILLD61a351</SongID>
          <SongName>Song 2</SongName>
          <SongComments>7221</SongComments>
        </Songs>
        <Songs>
          <SongID>mTnf0L5d6b9</SongID>
          <SongName>Song 3</SongName>
          <SongComments>21212</SongComments>
        </Songs>
        <Songs>
          <SongID>xOd2YIc7f69</SongID>
          <SongName>Song 4</SongName>
          <SongComments>422</SongComments>
        </Songs>
        <Songs>
          <SongID>mTmg866314c</SongID>
          <SongName>Song 5</SongName>
          <SongComments>81211</SongComments>
        </Songs>
    </AllSongs>
  </Xiami>
</rss>

Thisкод, который я использую для получения данных:

<?php
    foreach($xml->children() as $Artist) {
        $ArtistName     = $Artist->ArtistName;
        $Streaming      = $Artist->Streaming;
        $Fans           = $Artist->Fans;
        $SongsArrays    = $Artist->AllSongs;
        $SongsCount     = $Artist->AllSongs->Song->count();
    }
?>

Если я напечатаю print_r($SongsArrays), я получу следующий массив:

SimpleXMLElement Object
(
    [Song] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [SongID] => 8ILroS998dc
                    [SongName] => Song 1
                    [SongComments] => 9223
                )
            [1] => SimpleXMLElement Object
                (
                    [SongID] => 8ILLD61a351
                    [SongName] => Song 2
                    [SongComments] => 7221
                )
            [2] => SimpleXMLElement Object
                (
                    [SongID] => mTnf0L5d6b9
                    [SongName] => Song 3
                    [SongComments] => 21212
                )
            [3] => SimpleXMLElement Object
                (
                    [SongID] => xOd2YIc7f69
                    [SongName] => Song 4
                    [SongComments] => 422
                )
            [4] => SimpleXMLElement Object
                (
                    [SongID] => mTmg866314c
                    [SongName] => Song 5
                    [SongComments] => 81211
                )
        )
)

Если яраспечатать весь массив, я получаю это:

SimpleXMLElement Object
(
    [ArtistID] => 179
    [ArtistName] => Band 1
    [XiamiID] => 9dl4gN1c745
    [Streaming] => 246
    [Fans] => 84
    [AllSongs] => SimpleXMLElement Object
        (
            [Song] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [SongID] => 8ILroS998dc
                            [SongName] => Song 1
                            [SongComments] => 9223
                        )
                    [1] => SimpleXMLElement Object
                        (
                            [SongID] => 8ILLD61a351
                            [SongName] => Song 2
                            [SongComments] => 7221
                        )
                    [2] => SimpleXMLElement Object
                        (
                            [SongID] => mTnf0L5d6b9
                            [SongName] => Song 3
                            [SongComments] => 21212
                        )
                    [3] => SimpleXMLElement Object
                        (
                            [SongID] => xOd2YIc7f69
                            [SongName] => Song 4
                            [SongComments] => 422
                        )
                    [4] => SimpleXMLElement Object
                        (
                            [SongID] => mTmg866314c
                            [SongName] => Song 5
                            [SongComments] => 81211
                        )
                )
        )
)

Вопрос:

  1. Как мне извлечь первые 3 песни с дополнительными комментариями (получить комментарии, имя и идентификатор?))
  2. Как сложить все комментарии вместе? ...

Я перепробовал почти все, что рекомендует Google и другие форумы, но не могу найти, как получить эти данные без записиогромный код (разделяющий каждый массив и создающий много циклов) ... есть ли более быстрый и простой способ сделать это?

1 Ответ

0 голосов
/ 15 октября 2019

Вы можете использовать эту функцию, чтобы извлечь самые популярные песни для исполнителя. Он использует xpath, чтобы получить Songs из AllSongs, а затем usort, чтобы отсортировать этот список по SongComments по убыванию, наконец, используя array_slice, чтобы вернуть только 3 самых популярных песни:

function popular_songs($Artist) {
    $Songs = $Artist->xpath('//Songs');
    usort($Songs, function ($a, $b) { return $b->SongComments - $a->SongComments; });
    return array_slice($Songs, 0, 3);
}

Внутри вашего цикла вы бы назвали его следующим образом:

$PopularSongs   = popular_songs($Artist);

Если вы тогда print_r($PopularSongs) вы получите (дляваши образцы данных)

Array
(
    [0] => SimpleXMLElement Object
        (
            [SongID] => mTmg866314c
            [SongName] => Song 5
            [SongComments] => 81211
        )
    [1] => SimpleXMLElement Object
        (
            [SongID] => mTnf0L5d6b9
            [SongName] => Song 3
            [SongComments] => 21212
        )
    [2] => SimpleXMLElement Object
        (
            [SongID] => 8ILroS998dc
            [SongName] => Song 1
            [SongComments] => 9223
        )
)

Чтобы получить общее количество комментариев по исполнителю, вы можете использовать этот код, который находит все элементы SongComment, преобразует их в целые числа и суммирует их:

$TotalComments  = array_reduce($Artist->xpath('//SongComments'), function ($c, $v) { return $c + $v; }, 0);

Для ваших образцов данных это дает 119289.

Демонстрация на 3v4l.org

...