Asked  7 Months ago    Answers:  5   Viewed   38 times

I have the following XML file, the file is rather large and i haven't been able to get simplexml to open and read the file so i'm trying XMLReader with no success in php

<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
    <last_updated>2009-11-30 13:52:40</last_updated>
    <product>
        <element_1>foo</element_1>
        <element_2>foo</element_2>
        <element_3>foo</element_3>
        <element_4>foo</element_4>
    </product>
    <product>
        <element_1>bar</element_1>
        <element_2>bar</element_2>
        <element_3>bar</element_3>
        <element_4>bar</element_4>
    </product>
</products>

I've unfortunately not found a good tutorial on this for PHP and would love to see how I can get each element content to store in a database.

 Answers

42

It all depends on how big the unit of work, but I guess you're trying to treat each <product/> nodes in succession.

For that, the simplest way would be to use XMLReader to get to each node, then use SimpleXML to access them. This way, you keep the memory usage low because you're treating one node at a time and you still leverage SimpleXML's ease of use. For instance:

$z = new XMLReader;
$z->open('data.xml');

$doc = new DOMDocument;

// move to the first <product /> node
while ($z->read() && $z->name !== 'product');

// now that we're at the right depth, hop to the next <product/> until the end of the tree
while ($z->name === 'product')
{
    // either one should work
    //$node = new SimpleXMLElement($z->readOuterXML());
    $node = simplexml_import_dom($doc->importNode($z->expand(), true));

    // now you can use $node without going insane about parsing
    var_dump($node->element_1);

    // go to next <product />
    $z->next('product');
}

Quick overview of pros and cons of different approaches:

XMLReader only

  • Pros: fast, uses little memory

  • Cons: excessively hard to write and debug, requires lots of userland code to do anything useful. Userland code is slow and prone to error. Plus, it leaves you with more lines of code to maintain

XMLReader + SimpleXML

  • Pros: doesn't use much memory (only the memory needed to process one node) and SimpleXML is, as the name implies, really easy to use.

  • Cons: creating a SimpleXMLElement object for each node is not very fast. You really have to benchmark it to understand whether it's a problem for you. Even a modest machine would be able to process a thousand nodes per second, though.

XMLReader + DOM

  • Pros: uses about as much memory as SimpleXML, and XMLReader::expand() is faster than creating a new SimpleXMLElement. I wish it was possible to use simplexml_import_dom() but it doesn't seem to work in that case

  • Cons: DOM is annoying to work with. It's halfway between XMLReader and SimpleXML. Not as complicated and awkward as XMLReader, but light years away from working with SimpleXML.

My advice: write a prototype with SimpleXML, see if it works for you. If performance is paramount, try DOM. Stay as far away from XMLReader as possible. Remember that the more code you write, the higher the possibility of you introducing bugs or introducing performance regressions.

Wednesday, March 31, 2021
 
laurent
answered 7 Months ago
77

The site is blocking requests from PHP.

First run

<?php
ini_set('user_agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0');

(or some other valid user agent) and it will work.

Wednesday, March 31, 2021
 
altermativ
answered 7 Months ago
33

Your code has 2 errors.

1.) You assign email address to $mail from form. Then access $mail instance which should be mistaken as PHPMailer instance.

$mail = $_POST['mail'];
....
....
$mail->Subject = 'Reservation';
$mail->Body    = '<b>You have a reservation!</b></br>'
....
....

2.) You are exiting from execution inside foreach

if(!empty($_POST['check_list'])) {
    foreach($_POST['check_list'] as $check) {           
        return $check;
    }
}

Fix

$name    = $_POST['name'];
$surname = $_POST['surname'];
$email   = $_POST['mail'];
$phone   = $_POST['phone'];
$address = $_POST['address'];
$services= array();

if (!empty($_POST['check_list']) && is_array($_POST['check_list'])) {
    foreach ($_POST['check_list'] as $check) {           
        $services[] = $check;
    }
}

$mail = new PHPMailer;
//other PHPMailer config options
....
....
$mail->Subject = 'Reservation';
$mail->Body    = '<b>You have a reservation!</b></br>'
.'Name: '.$name.'</br>'
.'Surname: '.$surname.'</br>'
.'Mail: '.$email.'</br>'
.'Phone: '.$phone.'</br>'
.'Address: '.$address.'</br>'
.'Services: '. implode(', ', $services);

if (!$mail->send()) {
    echo 'Message could not be sent.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message has been sent';
    header('Location: index.php');
    exit();
}
Saturday, May 29, 2021
 
pocketfullofcheese
answered 5 Months ago
39

With some quick searching on how to retrieve XML via cURL this is what I did to retrieve and parse the XML.

The big reason as I mentioned above in a comment is that you can't pass URLs directly into the simple_xml_load_string function with ampersands(&) in them. It's a character in the XML format that represents entities.

<?php

function get_xml_from_url($url){
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');

    $xmlstr = curl_exec($ch);
    curl_close($ch);

    return $xmlstr;
}

$url = 'http://pubapi.yp.com/search-api/search/devapi/search?searchloc=91203&term=pizza&format=xml&sort=distance&radius=5&listingcount=10&key=t266jc29dx';
$contents = get_xml_from_url($url);

$xml = simplexml_load_string($contents);

echo '<pre>';
print_r($xml);
echo '</pre>';
?>
Saturday, May 29, 2021
 
StampyCode
answered 5 Months ago
66

I found a workaround:

First Install the package php-xml for my system: php-xml.x86_64

Package description: php-xml.x86_64 : A module for PHP applications which use XML

Install the above mentioned package(respective to your system) to enable XMLReader, XMLWriter.

php -i

has this now:

'--with-libxml-dir=/usr' 
'--enable-xml' 
'--enable-xmlreader=shared' 
'--enable-xmlwriter=shared'

I have also tested whether the package is enabled by creating an object of XMLReader.
But, I think I will be going with SimpleXML because I have to read very small xml files & because of its lower memory consumption. Read here.

Saturday, May 29, 2021
 
devo
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :