【问题标题】:How to split an XML file into three new arrays based on one parameter?如何根据一个参数将 XML 文件拆分为三个新数组?
【发布时间】:2015-05-08 17:52:09
【问题描述】:

我创建了一个 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 上搜索了我能想到的所有内容,但我空手而归。

如果这是一个愚蠢的问题,我很抱歉,我才这样做了大约一周。

【问题讨论】:

    标签: php arrays xml wordpress


    【解决方案1】:

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

    <?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-&gt;high = "true";,但您可能指的是$school-&gt;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

    【讨论】:

      【解决方案2】:

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

      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 元素(我猜)并且您还没有分享您编写的School 课程的任何细节,所以我实际上无法告诉您您最终如何将其移到该类中,但是您可以轻松地为自己创建一个FilterIterator,它能够处理更具体的SimpleXMLElementSimpleXMLIterator(或者您可以将现有元素包装一次。

      这样的过滤器很容易实现:

      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 查询文档。

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

      因为这里不需要三个数组。您只是想以不同的方式显示三倍相同的数据。数据只存在一次,而不是三次。保持简单,然后您可以用一千种不同的方式来呈现这些数据,而无需修改代码。

      【讨论】:

        猜你喜欢
        • 2015-08-09
        • 2017-03-14
        • 1970-01-01
        • 2021-01-27
        • 1970-01-01
        • 1970-01-01
        • 2019-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多