Problemen met het uitlezen van de RSS-feed via SimpleXML
Ik ben bezig met het uitlezen van een Xml-feed, waarna ik deze wegschrijf in een SQL-database. Daarvoor gebruik ik de volgende code:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
$affectedRow = 0;
$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");
foreach ($xml->channel->item as $row) {
$Last_build = $row->lastBuildDate;
//Select data from XML
$title = $row->title;
$pubDate = $row->pubDate;
//Format the last date
$unixtime = strtotime($pubDate);
$Published_date = date("Y-m-d H:i:s",$unixtime);
//Check if published date is the latest.
$Check_last_date = mysqli_num_rows(mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'"));
if($Check_last_date == '0'){
$sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
}
$result = mysqli_query($conn, $sql);
if (! empty($result)) {
$affectedRow ++;
} else {
$error_message = mysqli_error($conn) . "\n";
}
}
?>
<?php
if ($affectedRow > 0) {
//$message = $affectedRow . " records inserted";
} else {
//$message = "No records inserted";
}
?>
$affectedRow = 0;
$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");
foreach ($xml->channel->item as $row) {
$Last_build = $row->lastBuildDate;
//Select data from XML
$title = $row->title;
$pubDate = $row->pubDate;
//Format the last date
$unixtime = strtotime($pubDate);
$Published_date = date("Y-m-d H:i:s",$unixtime);
//Check if published date is the latest.
$Check_last_date = mysqli_num_rows(mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'"));
if($Check_last_date == '0'){
$sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
}
$result = mysqli_query($conn, $sql);
if (! empty($result)) {
$affectedRow ++;
} else {
$error_message = mysqli_error($conn) . "\n";
}
}
?>
<?php
if ($affectedRow > 0) {
//$message = $affectedRow . " records inserted";
} else {
//$message = "No records inserted";
}
?>
Nu heb ik alleen één probleem: enkel de eerste regel wordt 25 keer in de database weggeschreven als deze er niet in staat. Ik had het werkend toen ik de RSS-link als lokaal bestand had staan (met exact de inhoud van de RSS-feed ge copy-pasted), maar nu ik deze verander in een link, werkt alleen de bovenste regel 25 keer. Wat doe ik fout?
Tim
Tim
Ik zou toch aanraden om de query in een aparte variabele op te slaan. Zo kan je makkelijker debuggen, en makkelijker foutafhandeling toevoegen.
Ik heb - zoals je aangaf - inderdaad de quotes weggehaald op regel 20. Daarnaast heb ik SQL nu losgehaald. Mijn code ziet er nu zo uit:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");
foreach ($xml->children() as $row1) {
foreach($row1->item as $row){
//Select data from XML
$title = $row->title;
$pubDate = $row->pubDate;
//Format the last date
$unixtime = strtotime($pubDate);
$Published_date = date("Y-m-d H:i:s",$unixtime);
//Check if published date is the latest.
$Sql_check_las_date = "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'";
$Check_last_date = mysqli_num_rows(mysqli_query($conn, $Sql_check_las_date));
if($Check_last_date == 0){
$sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
}
mysqli_query($conn, $sql);
}
}
?>
$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");
foreach ($xml->children() as $row1) {
foreach($row1->item as $row){
//Select data from XML
$title = $row->title;
$pubDate = $row->pubDate;
//Format the last date
$unixtime = strtotime($pubDate);
$Published_date = date("Y-m-d H:i:s",$unixtime);
//Check if published date is the latest.
$Sql_check_las_date = "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'";
$Check_last_date = mysqli_num_rows(mysqli_query($conn, $Sql_check_las_date));
if($Check_last_date == 0){
$sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
}
mysqli_query($conn, $sql);
}
}
?>
Zoals ik al aangaf, denk ik dat het licht aan de foreach. Immers, ik krijg wel 25 keer een regel erin. In eerste instantie laadt ik alles dus goed in. Als ik alleen één regel weg haal uit de SQL-database (lees: er komt een nieuwe post bij in de XML-file), gaat hij alle regels daaronder af, en worden alle onderstaande regels afgelopen.
Bijvoorbeeld:
Ik verwijder één regel uit de databsase, welke in de XML-file 10 items eronder heeft. Vervolgend worden er 10 regels met dezelfde datum en tekst in de SQL-database gezet.
Doe ik dit met een SQL-regel welke in de XML nog 19 regels eronder heeft, krijg ik 19 keer dezelfde alarmering in de tabel ge-insert.
Hoor graag van jullie!
Je moet enkel de childs uitlezen. En daarbij controleer je in jouw geval welke de laatste is, waarna je een INSERT-query uitvoert.
Ik denk dat je met enig debugwerk al best wel ver moet komen. Dus sla de query eens los op, en kijk eens of die wel goed werkt. En check ook eens: $Check_last_date.
Code (php)
Want als je query foutmeldingen oplevert zal num_rows uiteraard altijd gelijk zijn aan 0.
Gewijzigd op 11/02/2020 19:31:00 door Frank Nietbelangrijk
Ik zou @Ariën zijn voorstel volgen en alles eens debuggen.
Daarbij: het uitlezen van een feed en het wegschrijven naar een database zijn twee aparte dingen.
Die je prima in afzondering kunt behandelen.
Jouw vraagstuk is van de vorm: ik verricht achtereenvolgens handeling A B C D .... X Y Z en uit Z komt niet het gewenste resultaat. Waar gaat het mis? Sja... ergens tussen A en Z :).
Als je dit nu eens opsplitst in aparte onderdelen: zorg dat de uitvoer van A geschikt is als invoer van B et cetera. Op die manier deel je je probleem op in stukken.
Dus, lees eerst de feed eens uit en kijk wat voor data dit oplevert. Zorg dat dit geschikt is om in een database in te voeren. En daarbij moet je waarschijnlijk op een of andere manier vaststellen wat al in je database aanwezig is. Hiervoor heb je dus een of ander (uniek) criterium nodig waarbij je onderscheid kunt maken tussen reeds aanwezige en nieuwe items. Ook deze stap kun je in afzondering onderzoeken. En vervolgens (laatste) insert je enkel de nieuwe items.
Verdeel en heers.
Ik was een beetje blind voor mijn eigen fouten, maar heb het inmiddels opgelost.
Mijn probleem: de $result stond buiten de check. Daardoor werd deze voor iedere regel uitgevoerd, terwijl de $sql toch nog onthouden wordt uit de vorige (immers: ik definieer hem niet ergens op leeg). Ik heb deze nu binnen de if geplaatst, en nu werkt het wel zoals ik wil. Final code:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");
foreach ($xml->channel->item as $row) {
$Last_build = $row->lastBuildDate;
//Select data from XML
$title = $row->title;
$pubDate = $row->pubDate;
//Format the last date
$unixtime = strtotime($pubDate);
$Published_date = date("Y-m-d H:i:s",$unixtime);
//Check if published date is the latest.
$result = mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'");
if($result === false) {
echo mysqli_error($conn);
exit;
}
$Check_last_date = mysqli_num_rows($result);
if($Check_last_date == '0'){
$sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
$result = mysqli_query($conn, $sql);
}
}
?>
$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");
foreach ($xml->channel->item as $row) {
$Last_build = $row->lastBuildDate;
//Select data from XML
$title = $row->title;
$pubDate = $row->pubDate;
//Format the last date
$unixtime = strtotime($pubDate);
$Published_date = date("Y-m-d H:i:s",$unixtime);
//Check if published date is the latest.
$result = mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'");
if($result === false) {
echo mysqli_error($conn);
exit;
}
$Check_last_date = mysqli_num_rows($result);
if($Check_last_date == '0'){
$sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
$result = mysqli_query($conn, $sql);
}
}
?>
- Ariën - op 11/02/2020 19:21:53:
Een geneste foreach? Dat lijkt mij niet echt logisch?
Je moet enkel de childs uitlezen. En daarbij controleer je in jouw geval welke de laatste is, waarna je een INSERT-query uitvoert.
Je moet enkel de childs uitlezen. En daarbij controleer je in jouw geval welke de laatste is, waarna je een INSERT-query uitvoert.
@Ariën, dit lijkt inderdaad niet logisch nee. Toch kan ik met de $xml->channel->item - string deze niet werkend krijgen. Vandaag deze dubbele foreache'jes.
Allen bedankt voor de hulp!
Daarnaast pubDate en Published_date zeggen niet gelijk dat dit verschillende formaten zijn.
En waarom eerst $row->pubDate kopieren naar pubDate dan naar unixtime dan een nieuw format?
Je kunt deze stappen allemaal overslaan, en zelfs direct aan de query voeren mits je deze verder niet meer nodig hebt.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$Published_date = (new \DateTime($row->pubDate))->format('Y-m-d H:i:s');
//of direct
$Sql_check_las_date = "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '" . (new \DateTime($row->pubDate))->format('Y-m-d H:i:s') . "'";
?>
$Published_date = (new \DateTime($row->pubDate))->format('Y-m-d H:i:s');
//of direct
$Sql_check_las_date = "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '" . (new \DateTime($row->pubDate))->format('Y-m-d H:i:s') . "'";
?>
Toevoeging op 11/02/2020 20:34:54:
En in plaats van de check door eerst een SELECT uit te voeren en dan een INSERT als Published_date niet bestaat, kun je ook het veld Published_date een "UNIQUE KEY" geven. Dan gebruik je "INSERT IGNORE". Mocht de Published_date dat al bestaan, slaat die deze ook over.
Ook zouden prepared statements hier meerwaarde kunnen hebben omdat het elke keer eenzelfde soort query betreft.