如何根据一个参数将XML文件拆分为三个新数组?

时间:2015-03-07 01:36:50

标签: php arrays xml wordpress

我创建了一个PHP类,当您输入经度和纬度时,它会查找并返回附近学校的XML列表。我将它们输出到三个HTML表格中,一个用于小学,中学和高中。 XML源文件不包含该信息,只包括学校提供的等级范围,因此我使用正则表达式对它们进行排序,如下所示:

foreach($data as $school) {
       if (preg_match("/1[0-2]$/", $school->gradeRange)) {?>
       <tr><td><?=$school->name?></td>
       <td><address><?=$school->address?>, <?=$school->city?></address></td>

等等。这很好用,但是代码在内容页面上,我需要将排序机制移到类中,这让我感到困惑。我是新手,所以它可能是显而易见的,但我一整天都在搜索和阅读,无法找到解决方案。

在课程中我创建了这个函数:

function sortSchools() {

        foreach($this->xml as $school) {
            if (preg_match("/1[0-2]$/", $school->gradeRange)) {
                $this->high = "true";
            }

        }
    }

但它实际上并没有对数据本身做任何工作。有没有办法让这个函数将gradeRange节点与表达式匹配的学校分成他们自己的数组,所以我最终会为每个学校级别分别建立一个单独的数组?我已经搜索了我能想到的所有搜索内容,无论是在这里还是Google上,我都空手而归。

如果这是一个愚蠢的问题,我道歉,我只做了大约一个星期。

2 个答案:

答案 0 :(得分:0)

我在这里做了一些快速的事情,实际上并不是很漂亮,但它可能会有所帮助。

<?php

class School {
    public $gradeRange;
    public $name;
    public $address;
    public $city;

    public $high;

    public function __construct($gradeRange, $name, $address, $city) {
        $this->gradeRange = $gradeRange;
        $this->name = $name;
        $this->adress = $address;
        $this->city = $city;
    }
}

$data = array(
    new School(112, "springfield hs", "99 strt", "Springfield"),
    new School(111, "stuff hs", "blvd stuff", "stufftown"),
    new School(134, "univerisity (not an highschool)", "here", "charlestown"),
    new School(110, "paul", "23 rd", "poll"),
);

foreach ($data as $school) {
    if (preg_match("/1[0-2]$/", $school->gradeRange)) { ?>
        <tr>
            <td><?= $school->name ?></td>
            <td>
                <address><?= $school->address ?>, <?= $school->city ?></address>
            </td>
        </tr>
    <?php }
}

class SchoolSorter
{
    public $schools;

    /**
     * @param array|School $schools
     */
    public function __construct(array $schools)
    {
        //$xmlReadre = new XMLReader();
        //$xmlReadre->readString($xml);
        $this->schools = $schools;
    }

    public function sortSchools()
    {
        foreach ($this->schools as $school) {
            if (preg_match("/1[0-2]$/", $school->gradeRange)) {
                $school->high = "true";
            }
        }
    }
}

$that_scholl_sorter = new SchoolSorter(
    $data
);

echo "before: \n";
var_dump($that_scholl_sorter->schools);

$that_scholl_sorter->sortSchools();

echo "after: \n";
var_dump($that_scholl_sorter->schools);

这样的输出

        <tr>
            <td>springfield hs</td>
            <td>
                <address>, Springfield</address>
            </td>
        </tr>
            <tr>
            <td>stuff hs</td>
            <td>
                <address>, stufftown</address>
            </td>
        </tr>
            <tr>
            <td>paul</td>
            <td>
                <address>, poll</address>
            </td>
        </tr>
    before: 
array(4) {
  [0]=>
  object(School)#1 (6) {
    ["gradeRange"]=>
    int(112)
    ["name"]=>
    string(14) "springfield hs"
    ["address"]=>
    NULL
    ["city"]=>
    string(11) "Springfield"
    ["high"]=>
    NULL
    ["adress"]=>
    string(7) "99 strt"
  }
  [1]=>
  object(School)#2 (6) {
    ["gradeRange"]=>
    int(111)
    ["name"]=>
    string(8) "stuff hs"
    ["address"]=>
    NULL
    ["city"]=>
    string(9) "stufftown"
    ["high"]=>
    NULL
    ["adress"]=>
    string(10) "blvd stuff"
  }
  [2]=>
  object(School)#3 (6) {
    ["gradeRange"]=>
    int(134)
    ["name"]=>
    string(31) "univerisity (not an highschool)"
    ["address"]=>
    NULL
    ["city"]=>
    string(11) "charlestown"
    ["high"]=>
    NULL
    ["adress"]=>
    string(4) "here"
  }
  [3]=>
  object(School)#4 (6) {
    ["gradeRange"]=>
    int(110)
    ["name"]=>
    string(4) "paul"
    ["address"]=>
    NULL
    ["city"]=>
    string(4) "poll"
    ["high"]=>
    NULL
    ["adress"]=>
    string(5) "23 rd"
  }
}
after: 
array(4) {
  [0]=>
  object(School)#1 (6) {
    ["gradeRange"]=>
    int(112)
    ["name"]=>
    string(14) "springfield hs"
    ["address"]=>
    NULL
    ["city"]=>
    string(11) "Springfield"
    ["high"]=>
    string(4) "true"
    ["adress"]=>
    string(7) "99 strt"
  }
  [1]=>
  object(School)#2 (6) {
    ["gradeRange"]=>
    int(111)
    ["name"]=>
    string(8) "stuff hs"
    ["address"]=>
    NULL
    ["city"]=>
    string(9) "stufftown"
    ["high"]=>
    string(4) "true"
    ["adress"]=>
    string(10) "blvd stuff"
  }
  [2]=>
  object(School)#3 (6) {
    ["gradeRange"]=>
    int(134)
    ["name"]=>
    string(31) "univerisity (not an highschool)"
    ["address"]=>
    NULL
    ["city"]=>
    string(11) "charlestown"
    ["high"]=>
    NULL
    ["adress"]=>
    string(4) "here"
  }
  [3]=>
  object(School)#4 (6) {
    ["gradeRange"]=>
    int(110)
    ["name"]=>
    string(4) "paul"
    ["address"]=>
    NULL
    ["city"]=>
    string(4) "poll"
    ["high"]=>
    string(4) "true"
    ["adress"]=>
    string(5) "23 rd"
  }
}

在您的示例中,您使用的是$this->high = "true";,但您可能需要$school->high = "true";

它不是基于匹配来分割数据,但是你可以循环一个正则表达式数组并将正则表达式作为参数传递给sortSchools($regex),对该参数执行preg_match并让函数返回一个数组匹配学校。

这里没有愚蠢的问题;)。

您可以使用preg_match代替preg_grep来获取数组中匹配学校的索引

preg_grep("/1[0-2]$/", explode("\n", $input_lines));。您可能会发现此php live regex tester有用。

请注意,您也可以通过引用传递学校,请参阅PHP Documentation,但不建议这样做,请参阅this other question

答案 1 :(得分:0)

查看问题中的第一个代码示例:

foreach ($data as $school) {
   if (preg_match("/1[0-2]$/", $school->gradeRange)) {?>
   <tr><td><?=$school->name?></td>
   <td><address><?=$school->address?>, <?=$school->city?></address></td>

这里有一个典型的过滤条件,带有if子句。

您现在想要将其移出模板以外的$data

由于$data是一个simplexml元素(我猜)并且你还没有分享你已经写过的学校课程的任何细节,我实际上可以&# 39;告诉你如何最终将它移到该课程中,但是你可以轻松地创建一个能够处理更具体的 SimpleXMLElement FilterIteratorSimpleXMLIterator({3}}或者你可以将现有元素包裹一次。

这样的过滤器易于实现:

class HighSchools extends FilterIterator
{
    public function accept()
    {
        $school = $this->getInnerIterator()->current();

        return preg_match("/1[0-2]$/", $school->gradeRange);
    }
}

这是它自己的(假设您实例化 SimpleXMLIterator 而不是 SimpleXMLIterator ,它应该无问题)可以让您移动过滤器 - 条件超出foreach

$highSchools = new HighSchools($data);

foreach ($highSchools as $school) {
    echo $school->name, "\n";
}

由于您可能无法使用单个过滤器,因此您可以创建一系列过滤器类,以便更轻松地编写多个过滤器并减少重复的代码:

abstract class SchoolFilter extends FilterIterator
{
    final public function accept()
    {
        $school = $this->getInnerIterator()->current();

        return $this->acceptSchool($school);
    }
}

class HighSchools extends SchoolFilter
{
    public function acceptSchool($school)
    {
        return preg_match("/1[0-2]$/", $school->gradeRange);
    }
}

然后你可以在学校课堂内移动它。甚至可以从 SimpleXMLIterator 扩展,并制作一个能够为其自身的过滤集合提供访问器方法的特殊方法。

另一种选择是你已经取消了XML中学校的分类/代表,这样你就可以轻松地用xpath查询文档。

我希望这提供了一些方法来研究更加模块化的设计,以便您更容易找到放置过滤条件的位置,并使它们可以互换。

因为你不需要三个阵列。您只是想以相同的数据显示三次,但只是以不同的方式显示。数据只有一次 - 而不是三次。保持这么简单,然后您可以通过几千种不同的方式来呈现数据,只需很少的代码修改。