【发布时间】:2015-11-09 20:15:01
【问题描述】:
解决了这个 XML 解析项目的一系列其他问题(感谢一位可爱的 SO 用户),我现在陷入了下一个障碍。我正在将 SimpleXML 加载到一个数组中,对其进行排序,然后将其回显到页面中,并对数据进行分组。
我可以显示我的组标题并正确排序,但是当我尝试添加子组数据(这需要 xpath 将属性与父组匹配)时,我的输出只是第一个组标题。不确定这是否是我将数组结果与 xpath 混合的方式,但希望这里有人可以立即发现问题。
这是我的 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>
我希望按 yearname 升序对组标题进行排序,并按 eptnumber 升序对子组结果进行排序。
到目前为止,这是我的 PHP 代码:
<?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>";
}
}
?>
这是我在任何排序之前的输出:
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
非常感谢您能发现问题或提出改进建议。显然这是基于相同结构的示例/示例数据。
山姆
更新
仍然没有设法做到这一点,并且无法发现我在哪一点上出错了。最好的猜测是 foreach 语句中的 xpath,但我对这种类型的代码还不够熟悉,无法发现它。
我已经为 sort_obj_arr 切换了 xsort,因为我认为它是一个更好的函数。不幸的是,我得到的结果与以前完全相同。这是我更新的代码:
<?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>";
}
}
?>
【问题讨论】:
-
我猜我的 xpath 引用数组是不正确的,但我对代码还不够熟悉,无法发现错误,因为我有点想这么做。已更新我的问题。
-
是时候学习调试代码了。您的猜测非常正确,您是否收到错误消息?见eval.in/468492。您对 ep 排序太早,您需要在选择相关的后对其进行排序。
-
不幸的是,我的 PHP 设置没有给我错误代码 - 我将不得不开始使用 eval.in 进行测试。我试过重新排列,但现在得到eval.in/468509
-
在 PHP 中获取有用的错误消息:stackoverflow.com/questions/845021/…
标签: php arrays xml sorting xpath