PHP отображает данные из XML с запросом - PullRequest
1 голос
/ 07 марта 2019

У меня есть следующий скрипт, который отображает данные из xml.

events.xml

<SchoolCalendar>
<CalendarEvent>
    <StartTime>07:30</StartTime>
    <Title>test Title 1</Title>
    <Location>Room 1</Location>
</CalendarEvent>
<CalendarEvent>
    <StartTime>01:10</StartTime>
    <Title>test Title 2</Title>
    <Location>Room 15</Location>
</CalendarEvent>
<CalendarEvent>
    <StartTime>03:30</StartTime>
    <Title>test Title 3</Title>
    <Location>Room 18</Location>
</CalendarEvent>
<CalendarEvent>
    <StartTime>14:30</StartTime>
    <Title>test Title 4</Title>
    <Location>Room 21</Location>
</CalendarEvent>
<CalendarEvent>
    <StartTime>14:30</StartTime>
    <Title>test Title 5</Title>
    <Location>Room 12</Location>
</CalendarEvent>
<CalendarEvent>
    <StartTime>15:30</StartTime>
    <Title>test Title 6</Title>
    <Location>Room 111</Location>
</CalendarEvent>

php code:

    $today = date("H:i");
    $lib  = simplexml_load_file("events.xml");
    $query = $lib->xpath("/SchoolCalendar/CalendarEvent[StartTime = '14:30']");

    if( $query ) {
    foreach($query as $node){
        echo "<tr>";
        echo "<td>$node->StartTime</td>";
        echo "<td>$node->Title</td>";
        echo "<td>$node->Location</td>";
        echo "</tr>";
    }
    }
    else {

    }

СПриведенный выше код будет отображать только два события с начальным временем 14:30.Как я могу отобразить все будущие события, пробовал следовать, но ничего не отображается.

$query = $lib->xpath("/SchoolCalendar/CalendarEvent[StartTime >= '$today']");

Любая помощь будет высоко ценится, спасибо.

1 Ответ

2 голосов
/ 07 марта 2019

Кроме перебора всех событий и проверки его StartTime
теоретически есть решение XPath, использующее оператор >= с xs:time типами, подобными этому:

/SchoolCalendar/CalendarEvent[xs:time(concat(StartTime, ':00')) >= xs:time('14:00:00')]

Демоверсия

Однако для этого требуется XPath 2+, а с PHP у вас есть доступ только к XPath 1.0 (с некоторыми расширениями XPath 2). Тем не менее, это может быть сделано в XPath с использованием PHP 5 DOMXPath::registerPhpFunctions.

Пример кода:

$doc = new DOMDocument;
$doc->loadXML($xml); //from string
$xpath = new DOMXPath($doc);

// Register the php: namespace (required)
$xpath->registerNamespace("php", "http://php.net/xpath");
// Register PHP functions (time_greater_thanonly)
$xpath->registerPHPFunctions("time_greater_than");
function time_greater_than($nodes)
{
  // Return true if time is greater or equal than now
  return strtotime($nodes[0]->nodeValue) >= strtotime(date("H:i"));
}
// Call custom function on the CalendarEvent nodes instead of XQuery 2+ functions
$query = $xpath->query('/SchoolCalendar/CalendarEvent[php:function("time_greater_than", StartTime)]');

if ($query) {
  foreach ($query as $node) {
    echo "<tr>";
    $values = explode("\n", trim($node->nodeValue));
    foreach ($values as $str)
      echo "<td>$str</td>";
    echo "</tr>";
  }
}

PS: для доступа к выводу time_greater_than я просто использую explode(), чтобы получить значения из текстового содержимого текущего узла. Чтобы углубиться в узел в цикле foreach, используйте xquery с текущим $node как contextnode param:

$xpath->query(".//Location", $node)[0]->nodeValue

, например

if ($query) {
  foreach ($query as $node) {
    echo "<tr>";
    echo "<td>".$xpath->query('.//StartTime', $node)[0]->nodeValue."</td>";
    echo "<td>".$xpath->query('.//Title', $node)[0]->nodeValue."</td>";
    echo "<td>".$xpath->query('.//Location', $node)[0]->nodeValue."</td>";
    echo "</tr>";
  }
}

PPS: Никогда версии XQuery также не имеют fn:current-time(). Мне пришлось использовать фиксированный xs:time, чтобы заставить его работать.

...