Viewed   98 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

5

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.

Thursday, December 8, 2022
1

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.

Sunday, October 23, 2022
 
3

You could use xpath to simplify things. Without knowing the full details, I don't know if it will work in all cases:

$source = "route.xml";
$xmlstr = file_get_contents($source);
$xml = @simplexml_load_string($xmlstr);
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->xpath('//Instruction') as $instr) {
   $new_xml->addChild('instruction', (string) $instr);
}
echo $new_xml->asXML();

Output:

<?xml version="1.0"?>
<main><instruction>Start</instruction><instruction>End</instruction></main>

Edit: The file at http://www.gps.alaingroeneweg.com/route.xml is not the same as the XML you have in your question. You need to use a namespace like:

$xml = @simplexml_load_string(file_get_contents('http://www.gps.alaingroeneweg.com/route.xml'));
$xml->registerXPathNamespace('xls', 'http://www.opengis.net/xls'); // probably not needed 
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->xpath('//xls:Instruction') as $instr) {
  $new_xml->addChild('instruction', (string) $instr);
}
echo $new_xml->asXML();

Output:

<?xml version="1.0"?>
<main><instruction>Start (Southeast) auf Sihlquai</instruction><instruction>Fahre rechts</instruction><instruction>Fahre halb links - Ziel erreicht!</instruction></main>
Thursday, September 1, 2022
2

Ok I finally got it. On dreamhost, it is possible to use fastcgi and therefore declare environment variables with it. It consists of just adding this simple script

#!/bin/sh
export PHP_FCGI_CHILDREN=2
exec /home/USERNAME/YOURDOMAIN/cgi-bin/php.cgi

Which is where my compiled PHP5.3.1 was located. chmod 744 on that file called dispatch.fcgi which will be allowed more memory by dreamhost's watchdog.

After that I added to my domain's .htaccess the following:

Options +ExecCGI
AddHandler fastcgi-script fcg fcgi fpl
AddHandler php5-fastcgi .php
Action php5-fastcgi /dispatch.fcgi

now in the application's root I have another .htaccess with:

SetEnv APPLICATION_ENVIRONMENT staging

In a php script is is retrievable via getenv('REDIRECT_APPLICATION_ENVIRONMENT');

Saturday, August 6, 2022
 
4

When &#xe7; is "รง", then your encoding is Windows-1252 (or maybe ISO-8859-1), but not UTF-8.

Wednesday, September 21, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :