SimpleXML的PHP​​排序问题 [英] PHP sorting issue with simpleXML

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

问题描述

test.xml:

<?xml version="1.0"?>
<props>
<prop>
<state statename="Mississippi">
    <info>
        <code>a1</code>
        <location>Jackson</location>
    </info>
    <info>
        <code>d2</code>
        <location>Gulfport</location>
    </info>
    <info>
        <code>g6</code>
        <location>Hattiesburg</location>
    </info>
</state>
<state statename="Texas">
    <info>
        <code>i9</code>
        <location>Dallas</location>
    </info>
    <info>
        <code>a7</code>
        <location>Austin</location>
    </info>
</state>
<state statename="Maryland">
    <info>
        <code>s5</code>
        <location>Mount Laurel</location>
    </info>
    <info>
        <code>f0</code>
        <location>Baltimore</location>
    </info>
    <info>
        <code>h4</code>
        <location>Annapolis</location>
    </info>
</state>
</prop>
</props>

test.php

test.php

// start the sortCities
function sortCities($a, $b){
    return strcmp($a->location, $b->location);
}
// start the sortStates
function sortStates($t1, $t2) {
    return strcmp($t1['statename'], $t2['statename']);
}


$props = simplexml_load_file('test.xml');
foreach ($props->prop as $prop) {
    $sortedStates = array();
    foreach($prop->state as $states) {
        $sortedStates[] = $states;
        }
    usort($sortedStates, "sortStates"); // finish the sortStates
    /* --- */
    echo '<pre>'."\n";
    print_r($sortedStates);
    echo '</pre>'."\n"; 
    /* --- */
    foreach ($prop->children() as $stateattr) { // this doesn't do it
    //foreach($sortedStates as $hotel => @attributes){ // blargh!
        if(isset($stateattr->info)) {
            $statearr = $stateattr->attributes();
            echo '<optgroup label="'.$statearr['statename'].'">'."\n";
            $options = array();
            foreach($stateattr->info as $info) {
                $options[] = $info;                            
            }
            usort($options, "sortCities"); // finish the sortCities  
            foreach($options as $stateattr => $info){
                echo '<option value="'.$info->code.'">'.$info->location.'</option>'."\n";
            }
            echo '</optgroup>'."\n";
            } else {
                //empty nodes don't do squat
            }
    }
}  
?>

这是一个数组:

print_r($sortedStates);

打印出:

Array
(
    [0] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [statename] => Maryland
                )

            [info] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [code] => s5
                            [location] => Mount Laurel
                        )

                    [1] => SimpleXMLElement Object
                        (
                            [code] => f0
                            [location] => Baltimore
                        )

                    [2] => SimpleXMLElement Object
                        (
                            [code] => h4
                            [location] => Annapolis
                        )

                )

        )

    [1] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [statename] => Mississippi
                )

            [info] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [code] => a1
                            [location] => Jackson
                        )

                    [1] => SimpleXMLElement Object
                        (
                            [code] => d2
                            [location] => Gulfport
                        )

                    [2] => SimpleXMLElement Object
                        (
                            [code] => g6
                            [location] => Hattiesburg
                        )

                )

        )

    [2] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [statename] => Texas
                )

            [info] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [code] => i9
                            [location] => Dallas
                        )

                    [1] => SimpleXMLElement Object
                        (
                            [code] => a7
                            [location] => Austin
                        )

                )

        )

)

此:

// start the sortCities
function sortCities($a, $b){
    return strcmp($a->location, $b->location);
}

加上这部分代码:

    $options = array();
    foreach($stateattr->info as $info) {
        $options[] = $info;                            
    }
    usort($options, "sortCities"); // finish the sortCities  
    foreach($options as $stateattr => $info){
        echo '<option value="'.$info->code.'">'.$info->location.'</option>'."\n";
    }

可以很好地按每个optgroup中的位置"节点进行排序.

is doing a fine job of sorting by the 'location' node within each optgroup.

您可以看到,在数组中,我可以按属性"statename"对其进行排序.我遇到的麻烦是回显并合并这两个功能,以使其自动对州和城市进行排序,并形成所需的optgroup.

You can see that in the array I can make it sort by the attribute 'statename'. What I am having trouble with is echoing out and combining the two functions in order to have it auto sort both the states and the cities within and forming the needed optgroups.

我试图复制城市的线路并更改名称,但无济于事.

I tried copying the lines for the cities and changing the names called several ways to no avail.

因此,使用上面的XML结构,我试图使它看起来像这样:

So using the XML structure above, I am trying to get it to look like:

<optgroup label="Maryland">
<option value="h4">Annapolis</option>
<option value="f0">Baltimore</option>
<option value="s5">Mount Laurel</option>
</optgroup>
<optgroup label="Mississippi">
<option value="d2">Gulfport</option>
<option value="g6">Hattiesburg</option>
<option value="a1">Jackson</option>
</optgroup>
<optgroup label="Texas">
<option value="a7">Austin</option>
<option value="i9">Dallas</option>
</optgroup>

关于状态在XML中的排序顺序以及状态中节点中位置的排序方式如何,它们总是在创建optgroup时按字母顺序排序.

So as to no matter what order the states are ordered in the XML and no matter how the Locations are ordered in the node within the states, they always order alphabetically upon the creating of the optgroup.

Artefacto-

Artefacto-

最后2个代码块显示了按名称对节点(位置节点)进行排序的功能.

the last 2 code blocks show the function for sorting the nodes by name (the location nodes).


// start the sortCities
function sortCities($a, $b){
    return strcmp($a->location, $b->location);
}
// start the sortStates
function sortStates($t1, $t2) {
    return strcmp($t1['statename'], $t2['statename']);
}

第二个函数的确按数组中的属性(州名)进行排序,但是,将两个函数组合在一起或者将它们嵌套在一起,以便使州和城市按字母顺序排序,这让我很困惑.

the second function does sort by attribute (statename) in the array but, combing the two function or rather nesting them so that the states and the cities get sorted alphabetically has got me stumped.

@Artefacto,

@Artefacto,

感谢您的回复.似乎使其嵌套方式有意义.问题是,我的服务器均未运行PHP 5.3.因此,通用函数会抛出错误.我应该提到这个,但没有考虑.他们正在运行5.2.我一直在尝试将脚本还原回原来的位置,并且一直停留在某个部分.

Thanks for the reply. Seems to make sense the way it's nested. Issue is, none of my servers run PHP 5.3. So the generic functions are tossing errors. I should have mentioned this but didn't think about it. They are running 5.2. I have been trying to revert the script back and have gotten stuck with a section.

<?php
$doc = simplexml_load_file('test.xml');
$states =  get_object_vars($doc->prop->children());
$states = $states["state"];
function sortStates($t1, $t2) { 
    return strcmp($t1['statename'], $t2['statename']); 
};
usort($states, "sortStates");

/* this is just here for testing */
echo '<pre>';
print_r($states);
echo '</pre>';
/* end testing */

/*
array_walk($states,
    function (&$state) {
        $state = get_object_vars($state);
        array_walk($state["info"],
            function (&$el) {
                $el = get_object_vars($el);
            }
        );
        usort($state["info"],
            function($a, $b) { return strcmp($a["location"], $b["location"]); }
        );
    }
);
*/
?>

从array_walk开始的注释掉的部分.我无法弄清楚如何重写'function(&$ state)'而下一行不会消失.

The commented out section starting with the array_walk. I can't figure out how to rewrite the 'function (&$state)' with out the next line dying.

推荐答案

您要基于某些属性或元素值对SimpleXMLElement的列表进行排序.通常,您可以通过将列表变成一个数组,然后对该数组进行排序来实现此目的.

You want to sort a list of SimpleXMLElements based on some attribute or element value. You normally do this by turning the list into an array and then apply the sorting on that array.

在PHP中有用的功能是 iterator_to_array .它的工作是将simplexml中令人难以置信的内容转换为更固定"的数组.

A function helpful for that in PHP is iterator_to_array. It does the job to turn something that is so magic in simplexml into a more "fixed" array.

比方说您在$result->tour中的游览元素.默认情况下,simplexml在此处返回一个 iterator ,这是您无法开箱即用的内容.让我们将其转换为数组:

Let's say your tour elements in $result->tour. By default simplexml returns an iterator here, something you can not sort out of the box. Let's convert it into an array:

$tours = iterator_to_array($result->tour, false);

现在,$tours变量是一个包含每个<tour>元素作为SimplXMLElement的数组.现在,您可以使用数组函数对该数组进行排序. PHP手册概述了那些数组排序功能,我通常建议如何在php中对多维数组进行排序起点:

Now the $tours variable is an array containing each <tour> element as a SimplXMLElement. You can now sort that array with an array function. Those array sorting functions are outlined in the PHP manual and I normally suggest How do I sort a multidimensional array in php as a good starting point:

$tourDates = array_map(
    function($tour) {return trim($tour->next_bookable_date); },
    $tours
);

// sort $tours array by dates, highest to lowest
$success = array_multisort($tourDates, SORT_DESC, $tours);

就已经足够了.整个代码一目了然

And that's already it. The whole code at a glance:

$tours = iterator_to_array($result->tour, false);

$tourDates = array_map(
    function($tour) {return trim($tour->next_bookable_date); },
    $tours
);

// sort $tours array by dates, highest to lowest
$success = array_multisort($tourDates, SORT_DESC, $tours);

foreach ($tours as $tour) {
    ...
}

这篇关于SimpleXML的PHP​​排序问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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