Velké soubory xml a práce s nimi. – PHP – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Velké soubory xml a práce s nimi. – PHP – Fórum – Programujte.comVelké soubory xml a práce s nimi. – PHP – Fórum – Programujte.com

 

polonium0
Návštěvník
10. 7. 2011   #1
-
0
-

Ahojte,

plánuji ve svém projektu pracovat s velkými xml soubory. Třeba i 5MB. K těmto souborům budu přistupovat z netu přes url http://example.com/soubor.xml, a protože nechci zahlcovat paměť serveru jedním souborem. Chtěl bych načítat soubor postupně a to tak aby fce vracela vždy jeden element. Tím elementem je myšlen elm <shopitem></shopitem>, který obsahuje další elementy atd... Napadlo mě toto řešení.

Otevřu url přes fopen a poté tento soubor budu procházet přes funkci stream_get_contents. A tento blok dat poté zpracuju přes funkci simplexml_load_string.

Myslíte, že je to dobré řešení? Nebo vás napadá nějaké optimálnější?

Díky za odpověďi

Nahlásit jako SPAM
IP: 85.132.169.–
z_moravec
~ Redaktor
+3
Posthunter
10. 7. 2011   #2
-
+1
-
Zajímavé

A co použít třeba SAX nebo jiný nástroj na sekvenčí zpracování XML?

Nahlásit jako SPAM
IP: 83.240.110.–
Spát lze čtyři hodiny denně, spát déle je nemístný přepych.
Thomas Alva Edison
polonium0
Návštěvník
10. 7. 2011   #3
-
0
-
Nahlásit jako SPAM
IP: 85.132.169.–
z_moravec
~ Redaktor
+3
Posthunter
10. 7. 2011   #4
-
0
-

#3 polonium
JJ, ale s xml v php jsem už dlouho nedělal, předpokládám, že už budou existovat i schopnější nástroje/knihovny

Nahlásit jako SPAM
IP: 83.240.110.–
Spát lze čtyři hodiny denně, spát déle je nemístný přepych.
Thomas Alva Edison
polonium0
Návštěvník
10. 7. 2011   #5
-
0
-

Super díky za radu :) Až to bude pošlu zdroj :)

Nahlásit jako SPAM
IP: 85.132.169.–
marioff0
Expert
10. 7. 2011   #6
-
0
-
Nahlásit jako SPAM
IP: 195.78.44.–
Škoda, že život sa nedá "sejvovať", tak že by som po zlom životnom rozhodnutí mohol začať odznova :([br] Lenivosť je matka pokroku.[br][br] http://cut.sk/ - odstrihni si dlhý link
polonium0
Návštěvník
10. 7. 2011   #7
-
0
-

Super, díky. Tohle jsem zvládl :)

Jen bych to chtěl udělat více řízené, tzn. procházet to podobně jako výsledek dotazu na db. Jak to udělat vím. Stačí to procházet např. pomocí fce fseek(), problém je v tom, že ten soubor je not seekable.

Existuje nějaká možnost jak ten soubor otevřít aby bylo možný ho procházet?

Nahlásit jako SPAM
IP: 85.132.169.–
polonium0
Návštěvník
10. 7. 2011   #8
-
0
-

Teď mě napadlo zkusit otevřít nějakej socket tunel. Nebo jak se tomu nadává :)

Nahlásit jako SPAM
IP: 85.132.169.–
polonium0
Návštěvník
10. 7. 2011   #9
-
+2
-
Zajímavé

V průběhu dne jsem dokončil tu třídu. Není to úplně dokonalý ale účel to splní.

<?php

class ImportException extends Exception
{
}

class Import
{
	/** @var fopen resource */
	protected $handle;

  /** @var XML parser object */
	protected $parser;

	/** @var bool */
	protected $opened = false;

	/** @var bool */
	protected $feof = false;

	/** @var string */
	protected $item;

	/** @var string */
	protected $element;

	/** @var array */
	protected $parsed = array();

	/** @var integer */
	protected $length = 4096;



	/**
	 * konstructor
	 */
	public function __construct()
	{
		$this->parser = xml_parser_create();

		xml_set_object($this->parser, $this);
		xml_set_element_handler($this->parser, "onStartElement", "onEndElement");
		xml_set_character_data_handler($this->parser, "onContent");
	}



	/**
	 * destructor
	 */
	public function __destruct()
	{
		xml_parser_free($this->parser);
	}



	/**
	 *
	 * @param strign $name
	 */
	public function setElement($name)
	{
		$this->element = $name;
	}



	/**
	 *
	 */
	public function parse()
	{
		if (empty($this->element))
			throw new ImportException('Jmeno elementu nesmi byt prazdne!');

		if ($this->feof)
			return false;

		# do-while nacita tak dlouho, dokud v poli $this->parsed neni aspon jeden element
		do {
			$data = fread($this->handle, $this->length);
			$this->feof = feof($this->handle);

			xml_parse($this->parser, $data, $this->feof);

			# Pokud pole $this->parsed obsahuje aspon jeden element,
			# bude pole vyprazdneno a metoda vrati jeho obsah
			if (!empty($this->parsed)) {
				$parsed = $this->parsed;
				$this->parsed = array();
				return $parsed;
			}
		} while (true);
	}



	/**
	 * Otevre soubor pro cteni
	 *
	 * @param string $url	 	 	 
	 */
	public function open($url)
	{
		# Zkontroluje nastaveni php.ini
		if (ini_get('allow_url_fopen') === false) {

			# Pokud neni mozne nastavit php.ini, vyhodi vyjimku
			if (!is_callable('ini_set'))
				throw new ImportException('Neni mozne otevrit soubor z url! Funkce ini_set() neni povolena.');

			# Nastavi php.ini
			ini_set('allow_url_fopen', true);
		}

		# Otevre soubor z url
		if (!$this->handle = fopen($url, "rb")) {
			throw new ImportException("Nepodarilo se otevrit soubor z url '" . $url . "'!");
		}
	}



	/**
	 *
	 * @param resource $parser
	 * @param string $name
	 * @param array $attributes
	 */
	protected function onStartElement($parser, $name, array $attributes)
	{
		if ($name === $this->element) {
			$this->opened = true;
			$this->item = '<' . $name . '>';
			#$this->byte = xml_get_current_byte_index($parser);

		} elseif ($this->opened === true) {
			$this->item .= '<' . $name . '>';
		}
	}


  /**
	 *
	 * @param resource $parser
	 * @param string $name
	 */
	protected function onEndElement($parser, $name)
	{
		if ($name === $this->element) {
			$this->opened = false;
			$this->item .= '</' . $name . '>';
			#$this->offset = xml_get_current_byte_index($parser);
		
			$this->parsed[] = simplexml_load_string($this->item);
		}
		elseif ($this->opened === true) {
			$this->item .= '</' . $name . '>';
		}
	}


  /**
	 *
	 * @param resource $parser
	 * @param string $data
	 */
	protected function onContent($parser, $data)
	{
		if ($this->opened === true) {
			$this->item .= htmlspecialchars($data);
			#$this->byte = xml_get_current_byte_index($parser);
		}
	}

}

Příklad použití:

$url = 'example.com/soubor.xml';

$imp = new Import;
$imp->open($url);
$imp->setElement('elementName');

while ($data = $imp->parse()) {
foreach($data as $elementName) {
  # SimpleXML object
  print_r($elementName);
}
}

Příklad pro soubor.xml

<elementName>
	<elm1>Content</elm1>
	<elm2>Content</elm2>
</elementName>
<elementName>
	<elm1>Content</elm1>
	<elm2>Content</elm2>
</elementName>
Nahlásit jako SPAM
IP: 85.132.169.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 43 hostů

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý