使用PHP解析XML Feed以查找是否存在特定数据

时间:2014-12-03 22:10:32

标签: php xml rss simplexml

我需要检查XML Feed中是否存在Team1。如果Team1在XML Feed中出现两次,我只需要输出第一个实例。到目前为止,我只能输出两个实例。我该如何做到这一点?

$str = <<<'XML'
<DATAS>
    <DATA>
        <VISITOR>Team6</VISITOR>
        <HOME>Team7</HOME>
    </DATA>
    <DATA>
        <VISITOR>Team1</VISITOR>
        <HOME>Team2</HOME>
    </DATA>
    <DATA>
        <VISITOR>Team3</VISITOR>
        <HOME>Team1</HOME>
    </DATA>
    <DATA>
        <VISITOR>Team4</VISITOR>
        <HOME>Team5</HOME>
    </DATA>
</DATAS>    
XML;


$data = new SimpleXMLElement($str);

$found = false;

foreach ($data->DATA as $item) {
    $teamh = $item->HOME;
    $teamv = $item->VISITOR;


    if ($teamh == 'Team1' || $teamv == 'Team1') { 
        $found = true;

    echo 'Home Team: ' . $data->DATA->HOME . "\n";
    echo 'Away Team: ' . $data->DATA->VISITOR . "\n";
   }

}

2 个答案:

答案 0 :(得分:1)

这是如何完成任务1 ,检查Team1是否以及在Feed中的频率:

$xml = simplexml_load_string($x); // assume XML in $x
$team1 = $xml->xpath("/DATAS/DATA[VISITOR='Team1' or HOME='Team1']");
echo "Team1 is included " . count($team1) . " time(s) in the feed.";

此示例使用xpath()选择Team1为<DATA><VISITOR>的所有<HOME>个节点。 结果是可以计算的SimpleXML元素数组。

看到它有效:https://eval.in/230136

对于任务2 ,只有Team1输出一次(与每个Team只有一次相比),这是一种循环方式:

$team1count = 0;

foreach ($xml->DATA as $event) {

    $t[0] = $event->VISITOR;
    $t[1] = $event->HOME;

    $hasteam1 = in_array('Team1', $t);

    if (($hasteam1 AND $team1count == 0) OR (!$hasteam1)) { 

        echo "Visitor: " . $t[0] . PHP_EOL;
        echo "Home: " . $t[1] . PHP_EOL;
    }

    $team1count = $team1count + $hasteam1;
}

此方法使用检查当前节点中Team1是<VISITOR>还是<HOME>,并计算Team1的出现次数。如果Team1存在,但计数器= 0,或者Team1不存在,则会回显团队。当然,如果Team1在那里,计数器必须递增。

看到它有效:https://eval.in/230152

但等等,还有另一种解决方案,让我们以我们为任务1所做的为基础

// same code as above:
$xml = simplexml_load_string($x); // assume XML in $x
$team1 = $xml->xpath("/DATAS/DATA[VISITOR='Team1' or HOME='Team1']");

现在,我们只删除Team1中的所有<DATA>个节点,但是删除XML中的第一个节点:

$c = 0;
foreach ($team1 as $event) {
    if ($c > 0) unset($event[0]);
    $c++;
}

$team1是一个包含team1所有节点的数组,所以我们迭代它。我们不会删除第一个,而是删除所有其他内容,只需使用$c进行计数,然后仅unset()执行$count > 0

unset($event[0])从XML树中删除<DATA>节点。

现在,我们只需要遍历XML并输出所有剩余的节点:

foreach ($xml->DATA as $event) 
    echo "Visitor: " . $event->VISITOR . ", Home: " . $event->HOME . PHP_EOL; 

查看所有这些操作:https://eval.in/230157

答案 1 :(得分:1)

使用XPath。使用它可以轻松选择DOM树上的节点。 (SimpleXML在后台使用DOM)。以下是SimpleXMLElement::xpath()DOMXpath::evaluate()的方法。

选择所有活动数据:
/DATAS/DATA

只有当VISITOR或HOME是&#34; Team1&#34;:
/DATAS/DATA[VISITOR='Team1' or HOME='Team1']

统计他们:
count(/DATAS/DATA[VISITOR='Team1' or HOME='Team1'])

限制到第一个找到的节点:
/DATAS/DATA[VISITOR='Team1' or HOME='Team1'][1]

SimpleXMLElement::xpath()始终返回SimpleXMLElement对象的数组。所以它不能直接执行count(...) Xpath表达式。

您当然可以在返回值上使用PHP函数count()

count($datas->xpath("/DATAS/DATA[VISITOR='Team1' or HOME='Team1']"));

如果您只想输出团队的第一个事件数据(如果存在),则不需要计数。限制XPath中的结果将返回带有单个元素或空列表的列表/数组。

SimpleXML示例

$datas = simplexml_load_string($str);

$eventCount = count($datas->xpath("/DATAS/DATA[VISITOR='Team1' or HOME='Team1']"));
echo "Team1 is included $eventCount time(s) in the feed.\n";

$events = $datas->xpath("/DATAS/DATA[VISITOR='Team1' or HOME='Team1'][1]");
foreach ($events as $event) {
  echo "Visitor: {$event->VISITOR}, Home: {$event->HOME}\n"; 
}

DOM示例

$dom = new DOMDocument();
$dom->loadXml($str);
$xpath = new DOMXPath($dom);

$eventCount = $xpath->evaluate("count(/DATAS/DATA[VISITOR='Team1' or HOME='Team1'])");
echo "Team1 is included $eventCount time(s) in the feed.\n";

$events = $xpath->evaluate("/DATAS/DATA[VISITOR='Team1' or HOME='Team1'][1]");
foreach ($events as $event) {
  $visitor = $xpath->evaluate('string(VISITOR)', $event);
  $home = $xpath->evaluate('string(HOME)', $event);
  echo "Visitor: $visitor, Home: $home\n"; 
}