PHP中具有SimpleXML,xsort和xpath的排序数组的输出 [英] Output from sorted array with SimpleXML, xsort and xpath in PHP

查看:89
本文介绍了PHP中具有SimpleXML,xsort和xpath的排序数组的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过这个XML解析项目解决了一系列其他问题(感谢可爱的SO用户),现在我陷入了下一个障碍。我正在将SimpleXML加载到数组中,对其进行排序,然后将其回显到页面中以对数据进行分组。

Having solved a chain of other issues with this XML parsing project (thanks to a lovely SO user), I'm now stuck at the next hurdle. I'm loading SimpleXML into an array, sorting it and then echoing it into the page with grouping for the data.

我可以显示要正确显示的组标题,但是当我尝试添加子组数据(需要使用xpath将属性与父组匹配)时,我的输出只是第一个组标题。不知道这是否是我将数组结果与xpath混合的方式,但希望这里有人可以立即发现问题。

I can get my group headings to display, sorted correctly, however when I try to add the sub-group data (which requires xpath to match attributes to the parent group), my output is just the first group heading. Not sure if it's the way I'm mixing array results with xpath or not but hopefully somebody here can spot the issue straight away.

这是我的XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE besteplist SYSTEM "example.dtd">
<besteplist>
    <yearlist>
        <year yid="y1">
            <yearname>1995, Season 3</yearname>
        </year>
        <year yid="y2">
            <yearname>1996, Season 4</yearname>
        </year>
        <year yid="y3">
            <yearname>1997, Season 5</yearname>
        </year>
        <year yid="y4">
            <yearname>1994, Season 2</yearname>
        </year>
        <year yid="y5">
            <yearname>1993, Season 1</yearname>
        </year>
    </yearlist>
    <eplist>
        <ep yearid="y1" eid="e1">
            <eptitle>The Third Episode</eptitle>
            <eptnumber>3</eptnumber>
        </ep>
        <ep yearid="y2" eid="e2">
            <eptitle>Bla bla bla</eptitle>
            <eptnumber>21</eptnumber>
        </ep>
        <ep yearid="y2" eid="e3">
            <eptitle>Rar rar rar</eptitle>
            <eptnumber>39</eptnumber>
        </ep>
        <ep yearid="y2" eid="e4">
            <eptitle>Tra la la</eptitle>
            <eptnumber>45</eptnumber>
        </ep>
        <ep yearid="y3" eid="e5">
            <eptitle>Donkey</eptitle>
            <eptnumber>126</eptnumber>
        </ep>
        <ep yearid="y1" eid="e6">
            <eptitle>SHOULD APPPEAR AS FIRST ONCE SORTED</eptitle>
            <eptnumber>1</eptnumber>
        </ep>
    </eplist>
</besteplist>

我想按年份名称将组标题按升序排序,将子组结果按eptnumber升序进行排序

I am looking to sort the group headers by yearname in ascending order and the subgroup results by eptnumber in ascending order.

这是我到目前为止的PHP代码:

Here is my PHP code so far:

<?php
$xml=simplexml_load_file("example.xml") or die("Error: Cannot create object");

function xsort(&$sorted_year, $child_name, $order=SORT_ASC)
{
    $sort_proxy = array();

    foreach ($sorted_year as $k => $node) {
        $sort_proxy[$k] = (string) $node->$child_name;
    }

    array_multisort($sort_proxy, $order, $sorted_year);
}

$sorted_year = $xml->xpath('/besteplist/yearlist/year');
xsort($sorted_year, 'yearname', SORT_ASC);

$sorted_ep = $xml->xpath('/besteplist/eplist/ep');
xsort($sorted_ep, 'eptnumber', SORT_ASC);

foreach ($sorted_year as $season) {
    echo "SEASON: " . $season->yearname . "<br>";
    foreach ($sorted_ep->xpath("//ep[@yearid='$season[yid]']") as $episode) { 
        echo "EPISODE TITLE: " . $episode->eptitle . PHP_EOL . "<br>";
        echo "EPISODE NUMBER: " . $episode->eptnumber . PHP_EOL . "<br>"; 
        echo PHP_EOL . "<br>";
    }
}


?>

这是我在进行任何排序之前的输出:

This is my output before any sorting:

SEASON: 1995, Season 3
EPISODE TITLE: The Third Episode 
EPISODE NUMBER: 3 

EPISODE TITLE: SHOULD APPPEAR AS FIRST ONCE SORTED 
EPISODE NUMBER: 1 

SEASON: 1996, Season 4
EPISODE TITLE: Bla bla bla 
EPISODE NUMBER: 21 

EPISODE TITLE: Rar rar rar 
EPISODE NUMBER: 39 

EPISODE TITLE: Tra la la 
EPISODE NUMBER: 45 

SEASON: 1997, Season 5
EPISODE TITLE: Donkey 
EPISODE NUMBER: 126 

SEASON: 1994, Season 2
SEASON: 1993, Season 1

应显示为:

SEASON: 1993, Season 1

SEASON: 1994, Season 2

SEASON: 1995, Season 3
EPISODE TITLE: SHOULD APPPEAR AS FIRST ONCE SORTED 
EPISODE NUMBER: 1 

EPISODE TITLE: The Third Episode 
EPISODE NUMBER: 3 

SEASON: 1996, Season 4
EPISODE TITLE: Bla bla bla 
EPISODE NUMBER: 21 

EPISODE TITLE: Rar rar rar 
EPISODE NUMBER: 39 

EPISODE TITLE: Tra la la 
EPISODE NUMBER: 45 

SEASON: 1997, Season 5
EPISODE TITLE: Donkey 
EPISODE NUMBER: 126 

如果可以发现问题或提出改进建议,请多谢。显然,这是基于相同结构的样本/示例数据。

Many thanks in advance if you can spot the problem or suggest improvements. Obviously this is sample/example data based on the same structure.

Sam

UPDATE

仍然没有做到这一点,也无法发现我错了。最好的猜测是foreach语句中的xpath,但是我对这种类型的代码不够熟悉,无法发现它。

Still haven't managed to get this quite right and unable to spot which point I'm going wrong at. Best guess would be the xpath within the foreach statement, but I'm not familiar enough with this type of code to be able to spot it.

我已经退出了我认为xsort是sort_obj_arr的更好功能。不幸的是,我得到的结果和以前完全一样。这是我更新的代码:

I've switched out xsort for sort_obj_arr as I assume it's a somewhat better function. Unfortunately I'm getting the exact same results as before. Here's my updated code:

<?php
$xml=simplexml_load_file("example.xml") or die("Error: Cannot create object");

function sort_obj_arr(& $arr, $sort_field, $sort_direction) {
    $sort_func = function($obj_1, $obj_2) use ($sort_field, $sort_direction) {
        if ($sort_direction == SORT_ASC) {
            return strnatcasecmp($obj_1->$sort_field, $obj_2->$sort_field);
        } else {
            return strnatcasecmp($obj_2->$sort_field, $obj_1->$sort_field);
        }
    };
    usort($arr, $sort_func);
}

$sorted_year = $xml->xpath('/besteplist/yearlist/year');
$field1 = 'yearname';
$direction1 = SORT_ASC;
sort_obj_arr($sorted_year, $field1, $direction1);

$sorted_ep = $xml->xpath('/besteplist/eplist/ep');
$field2 = 'eptnumber';
$direction2 = SORT_ASC;
sort_obj_arr($sorted_ep, $field2, $direction2);

foreach ($sorted_year as $season) {
    echo "SEASON: " . $season->yearname . "<br>";
    foreach ($sorted_ep->xpath("//ep[@yearid='$season[yid]']") as $episode) { 
        echo "EPISODE TITLE: " . $episode->eptitle . PHP_EOL . "<br>";
        echo "EPISODE NUMBER: " . $episode->eptnumber . PHP_EOL . "<br>"; 
        echo PHP_EOL . "<br>";
    }
}

?>


推荐答案

您的代码

foreach ($sorted_ep->xpath("//ep[@yearid='$season[yid]']") as $episode)

抛出错误

Fatal error: Call to a member function xpath() on a non-object (...)



<上调用成员函数xpath() p>因为 $ sorted_ep 是一个数组,而不是 SimpleXml 对象。

because $sorted_ep is an array, not a SimpleXml-object.

获取全部 < ep> 的排序列表是没有意义的在您的XML中。您需要选择特定年份的情节,然后对它们进行排序:

It makes no sense to get a sorted list of all <ep> in your XML. You need to select the episodes for a certain year, and then sort those:

foreach ($sorted_year as $season) {
    echo "SEASON: " . $season->yearname . "<br><br>";

    // first select episodes from a certain year 
    $episodes = $xml->xpath("//ep[@yearid='$season[yid]']");

    // then sort those
    sort_obj_arr($episodes, "eptnumber", SORT_ASC);

    // now iterate and echo
    foreach ($episodes as $episode) { 
        echo "  EPISODE TITLE: " . $episode->eptitle . "<br>";
        echo "  EPISODE NUMBER: " . $episode->eptnumber . "<br><br>"; 
    }
}

查看实际操作: https://eval.in/468571

这篇关于PHP中具有SimpleXML,xsort和xpath的排序数组的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆