Filling XML with loops in PHP - php

I got the following code but nothing happens, I can't find a good tutorial on filling XML with multiple loops:
$xml = new DOMDocument();
$xml->formatOutput = true;
$xml_user = $xml->createElement("User");
$xml_user->setAttribute("Name", $username);
foreach ($alben as $album) {
$i = 1;
$xml_album = $xml->createElement("Album");
$pictures = $picture_object->get_all_pictures($album['id']);
$xml_user->appendChild($xml_album);
$xml_album->setAttribute("Name", $album['name']);
foreach ($pictures as $picture) {
$xml_picture = $xml->createElement("Picture");
$xml_album->appendChild($xml_picture);
$xml_picture->setAttribute("Name", $picture['name']);
$rating = $rating_object->get_picture_rating($picture['id']);
$xml_rating = $xml->createElement("Rating");
$xml_picture->appendChild($xml_rating);
$comments = $comment_object->get_all_comments($picture['id']);
foreach ($comments as $comment) {
$xml_comment = $xml->createElement("Kommentar");
$xml_picture->appendChild($xml_comment);
$xml_comment->setAttribute("Datum", $comment['date']);
$xml_comment->nodeValue($comment['text']);
}
}
}
$xml->save("myXML.xml");

Related

How to scrape data from HTML Table in PHP

Hey I've been trying to scrape data from an html table and I'm not having much luck.
Website: https://www.dnr.state.mn.us/hunting/seasons.html
What I'm trying to do: I want to grab the contents of the table and encode it into json like
['event_title' 'Waterfowl'] and ['event_date' '09/25/21']
but I don't know how to do this, I've tried a couple different things but in the end I can't get it to work.
Code Example (Closest I got):
<?php
$dom = new DOMDocument;
$page = file_get_contents('https://www.dnr.state.mn.us/hunting/seasons.html');
$dom->loadHTML($page);
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//tbody/tr') as $tr) {
$tmp = []; // reset the temporary array so previous entries are removed
foreach ($xpath->query("td[#class]", $tr) as $td) {
$key = preg_match('~[a-z]+$~', $td->getAttribute('class'), $out) ? $out[0] : 'no_class';
if ($key === "event-title") {
$tmp['event_title'] = $xpath->query("a", $td);
}
$tmp[$key] = trim($td->textContent);
}
//$tmp['event_date'] = date("M. dS 'y", strtotime(preg_replace('~\.|\d+[ap]m *~', '', $tmp['date'])));
//$result[] = $tmp;
$marray[] = array_unique($tmp);
print_r($marray);
}
//$array2 = var_export($result);
//print_r($array2[1]);
//var_export($result);
//echo "\n----\n";
//echo json_encode($result);
?>

How to create looped XML file from HTML in PHP?

I would like to be able to create an XML file from some of the content of a html page. I have tried intensively but seem to miss something.
I have created two arrays, I have setup a DOMdocument and I have prepared to save an XML file on the server... I have tried to make tons of different foreach loops all over the place - but it won't work.
Here is my code:
<?php
$page = file_get_contents('http://www.halfmen.dk/!hmhb8/score.php');
$doc = new DOMDocument();
$doc->loadHTML($page);
$score = $doc->getElementsByTagName('div');
$keyarray = array();
$teamarray = array();
foreach ($score as $value) {
if ($value->getAttribute('class') == 'xml') {
$keyarray[] = $value->firstChild->nodeValue;
$teamarray[] = $value->firstChild->nextSibling->nodeValue;
}
}
print_r($keyarray);
print_r($teamarray);
$doc = new DOMDocument('1.0','utf-8');
$doc->formatOutput = true;
$droot = $doc->createElement('ROOT');
$droot = $doc->appendChild($droot);
$dsection = $doc->createElement('SECTION');
$dsection = $droot->appendChild($dsection);
$dkey = $doc->createElement('KEY');
$dkey = $dsection->appendChild($dkey);
$dteam = $doc->createElement('TEAM');
$dteam = $dsection->appendChild($dteam);
$dkeytext = $doc->createTextNode($keyarray);
$dkeytext = $dkey->appendChild($dkeytext);
$dteamtext = $doc->createTextNode($teamarray);
$dteamtext = $dteam->appendChild($dteamtext);
echo $doc->save('xml/test.xml');
?>
I really like simplicity, thank you.
You need to add each item in one at a time rather than as an array, which is why I build the XML for each div tag rather than as a second pass. I've had to assume that your XML is structured the way I've done it, but this may help you.
$page = file_get_contents('http://www.halfmen.dk/!hmhb8/score.php');
$doc = new DOMDocument();
$doc->loadHTML($page);
$score = $doc->getElementsByTagName('div');
$doc = new DOMDocument('1.0','utf-8');
$doc->formatOutput = true;
$droot = $doc->createElement('ROOT');
$droot = $doc->appendChild($droot);
foreach ($score as $value) {
if ($value->getAttribute('class') == 'xml') {
$dsection = $doc->createElement('SECTION');
$dsection = $droot->appendChild($dsection);
$dkey = $doc->createElement('KEY', $value->firstChild->nodeValue);
$dkey = $dsection->appendChild($dkey);
$dteam = $doc->createElement('TEAM', $value->firstChild->nextSibling->nodeValue);
$dteam = $dsection->appendChild($dteam);
}
}

How do I rename XML values using php?

How do I rename a value in xml using PHP? This is what I've got so far:
<?php
$q = $_GET["q"];
$q = stripslashes($q);
$q = explode('|^', $q);
$old = $q[0];
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->Load("test.xml");
$xpath = new DOMXPath($dom);
$query1 = 'channel/item[title="' . $old . '"]/title';
$entries = $xpath->query($query1);
foreach ($entries as $entry)
{
$oldchapter = $entry->parentNode->removeChild($entry);
$item = $dom->getElementsByTagName('item');
foreach ($item as $items)
{
$title = $dom->createElement('title', $q[1]);
$items->appendChild($title);
}
}
$dom->save("test.xml");
Basically, what it does is take two titles from a url, the old existing title, and the one the user wants to change it to (so like this oldtitle|^newtitle), and puts them into an array.
What I've tried doing is removing the existing old title, and then making a new title with, using the new title value from the url, but it doesn't seem to be working. Where am I going wrong, or is there an easier way of doing this?
The way to do this is with DOMNode::replaceChild(). The majority of your code is correct, you've just slightly over-complicated some of the DOM stuff.
Try this:
<?php
$q = $_GET["q"];
$q = stripslashes($q);
$q = explode('|^', $q);
$old = $q[0];
$dom = new DOMDocument;
// Do this *before* loading the document
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->Load("test.xml");
$xpath = new DOMXPath($dom);
$query1 = 'channel/item[title="' . $old . '"]/title';
$entries = $xpath->query($query1);
// This is all you need to do in the loop
foreach ($entries as $oldTitle) {
$newTitle = $dom->createElement('title', $q[1]);
$entry->parentNode->replaceChild($newTitle, $oldTitle);
}
$dom->save("test.xml");

Xpath for extracting links

I create an scraper for an automoto site and first I want to get all manufactures and after that all links of models for each manufactures but with the code below I get only the first model on the list. Why?
<?php
$dom = new DOMDocument();
#$dom->loadHTMLFile('http://www.auto-types.com');
$xpath = new DOMXPath($dom);
$entries = $xpath->query("//li[#class='clearfix_center']/a/#href");
$output = array();
foreach($entries as $e) {
$dom2 = new DOMDocument();
#$dom2->loadHTMLFile('http://www.auto-types.com' . $e->textContent);
$xpath2 = new DOMXPath($dom2);
$data = array();
$data['newLinks'] = trim($xpath2->query("//div[#class='modelImage']/a/#href")->item(0)->textContent);
$output[] = $data;
}
echo '<pre>' . print_r($output, true) . '</pre>';
?>
SO I need to get: mercedes/100, mercedes/200, mercedes/300 but now with my script i get only the first link so mercedes/100...
please help
You need to iterate through the results instead of just taking the first item:
$items = $xpath2->query("//div[#class='modelImage']/a/#href");
$links = array();
foreach($items as $item) {
$links[] = $item->textContent;
}
$data['newLinks'] = implode(', ', $links);

Getting element names/values with XML/Xpath/PHP

I have an XML schema that looks as follows:
<xml>
<user id="1">
<first_name>Bill</first_name>
<last_name>Steve</last_name>
<phone_numbers>
<work>xxx-xxx-xxxx</work>
<home>xxx-xxx-xxxx</home>
</phone_numbers>
</user>
<user id="2">
........
</user>
</xml>
Im working on parsing all of this information into PHP using DOM. Ex.
$userInfo = $doc->getElementsByTagName( "user" );
foreach($userInfo as $row)
{
$first_name = $row->getElementsByTagName("first_name");
}
When I try to nest this to select the phone numbers however I get an error. I've tried using XPath to select the phone numbers with equal problems. I tried something along the lines of
$userInfo = $doc->getElementsByTagName( "user" );
foreach($userInfo as $row)
{
$phoneInfo = $row->getElementsByTagName("phone_numbers");
foreach($phoneInfo as $row2)
{
$work = $row2->getElementsByTagName("work");
}
}
Im curious if Im doing something fundamentally wrong, or how to get this going. I've been tearing my hair out for a few hours now.
You can't get the value directly from a DOMNodeList Object, try this :
$userInfo = $doc->getElementsByTagName( "user" );
foreach($userInfo as $row)
{
$phoneInfo = $row->getElementsByTagName("phone_numbers");
foreach($phoneInfo as $row2)
{
// get the value from the first child
$work = $row2->getElementsByTagName("work")->item(0)->nodeValue;
$home = $row2->getElementsByTagName("home")->item(0)->nodeValue;
}
}
Well, you could switch it to SimpleXml which makes this type of parsing easier:
$userInfo = $doc->getElementsByTagName( "user" );
foreach ($userInfo as $user) {
$node = simplexml_import_dom($user);
$id = (string) $node['id'];
$first = (string) $node->first_name;
$last = (string) $node->last_name;
$workPhone = (string) $node->phone_numbers->work;
$homePhone = (string) $node->phone_numbers->home;
}
Now, in DomDocument, you could do this by using DomXpath:
$userInfo = $doc->getElementsByTagName( "user" );
$xpath = new DomXpath($doc);
foreach ($userInfo as $user) {
$id = $user->getAttribute('id');
$first = $xpath->query('//first_name', $user)->item(0)->textContent;
$last = $xpath->query('//last_name', $user)->item(0)->textContent;
$work = $xpath->query('//phone_numbers/work', $user)->item(0)->textContent;
$home = $xpath->query('//phone_numbers/home', $user)->item(0)->textContent;
}
Note that the above code (both parts) require that the format is exactly that. If you have conditionals, you might want to change it to something like this (the firstname conditional only):
$userInfo = $doc->getElementsByTagName( "user" );
$xpath = new DomXpath($doc);
foreach ($userInfo as $user) {
$id = $user->getAttribute('id');
$firstQuery = $xpath->query('//first_name', $user);
if ($firstQuery->length > 0) {
$first = $firstQuery->item(0)->textContent;
} else {
$first = '';
}
}

Categories