Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

PHP & DOM; interní poznámky

Pár postřehů k DOM API v PHP 5. Jde o funkce pro parsování, generování a manipulaci s XML a HTML soubory. Chování se může v různých verzích lišit.

$dom = new DOMDocument();

// konfigurace pro načtení
$dom->preserveWhiteSpace = FALSE;
$dom->load('input.xml');

// konfigurace pro uložení
$dom->formatOutput = TRUE;
$dom->encoding = 'utf-8';
$dom->save('output.xml');

Načtení XML souboru

  • metody $dom->load($fileName), $dom->loadXML($string)
  • konfigurační vlastnosti:
    • $dom->resolveExternals – načíst externí entity z DTD deklarace? Výchozí: FALSE
    • $dom->strictErrorChecking – throws DOMException on errors? Výchozí: TRUE
    • $dom->validateOnParse – načíst a validovat oproti DTD? Vychozí: FALSE
    • $dom->preserveWhiteSpace – zachovat redundantní white space? Výchozí: TRUE
    • $dom->substituteEntities – zaměnit jmenné entity? Výchozí: FALSE
  • validování nebo resolveExternals stahuje DTD – extrémně pomalé!
  • aby se nestahovalo DTD:
    • ponechat nastavené resolveExternals = validateOnParse = FALSE
    • nebo použít XML Catalogs (nepovedlo se mi rozchodit)
    • nebo modifikovat URL v <!DOCTYPE> na lokální kopii DTD
  • zpracování DTD je pomalé (tj. i bez stahování)
    • načtení XHTML dokumentu trvá cca 50× déle
    • validování už pak zpomalí jen mírně
  • bez zpracování DTD:
  • $dom->encoding určuje XML deklarace

Uložení XML souboru

  • metody $dom->save($fileName), $s = $dom->saveXML()
  • generují identický výstup (narozdíl od ukládání HTML)
  • konfigurační vlastnosti:
    • $dom->formatOutput – generuje „hezčí“ výstup (formátuje podivně)
    • $dom->encoding – kódování (např. utf-8, windows-1250)
    • $dom->standalone, $dom->version – XML deklarace
  • formatOutput lze povolit jen tehdy, pokud bylo načítáno s preserveWhiteSpace == FALSE
  • saveXML($node) s parametrem ignoruje encoding, vždy používá UTF-8

Načtení HTML souboru

  • metody $dom->loadHTMLFile($fileName), $dom->loadHTML($string)
  • chápe všechny HTML entity
  • ignoruje nastavení:
    • $dom->resolveExternals (vždy TRUE)
    • $dom->validateOnParse (vždy FALSE)
    • $dom->preserveWhiteSpace (vždy TRUE)
    • $dom->substituteEntities (vždy TRUE)
  • je nutné specifikovat kódování meta hlavičkou, jinak použje ISO-8859-1, ale vlastnost $dom->encoding nastaví na NULL a už nepůjde změnit při ukládání
  • přepisuje \r na &#13; → odstranit funkcí str_replace
  • funguje getElementById()
  • nevytváří plnohodnotný DOM, nedoplní např. element body (má volitelné značky)

Uložení HTML souboru

  • metody $dom->saveHTMLFile($fileName), $s = $dom->saveHTML()
  • negenerují stejný výstup!
  • pokud byl vstup načten jako XML (load, loadXML), ukládá špatně prázdné elementy
  • ignoruje nastavení:
    • $dom->formatOutput (vždy FALSE)
    • $dom->encoding
      • saveHTML použije vstupní kódování
      • saveHTMLFile použije 7bit ASCII, v meta hlavičce uvádí UTF-8 (není chyba),

Zpracování HTML souboru

// odstraníme \r
$s = file_get_contents('input.html');
$s = str_replace("\r", '', $s);

// parsujeme
$dom = new DOMDocument();
$ok = $dom->loadHTML($s);

// zjistíme obsah <title>
$title = $dom->getElementsByTagName('title')->item(0)->nodeValue;

// nebo šikovněji přes XPath:
$xpath = new DOMXPath($dom);
$title = $xpath->query('//title')->item(0)->nodeValue;

XPath: tutorial, XPather extension

Komentáře

  1. David Grudl http://davidgrudl.com #1

    avatar

    Tohle není článek, jen souhrn mých rešerší, sepsaný pro vlastní potřebu. Text nadále doplňuji a upravuji. Budu rád, pokud téma doplníte o další postřehy.

    před 9 lety
  2. pixy http://pixy.cz #2

    Prefix: mám s tímhle nulové zkušenosti; drobný nápad: nepomohlo by přeuložit nepoužívanější DTD na lokál a přesměrovat PHP na ně?

    před 9 lety | reagoval [3] David Grudl
  3. David Grudl http://davidgrudl.com #3

    avatar

    #2 pixy, asi nejsnáze to lze udělat změnou URL v <!DOCTYPE>na lokální soubor, zprovoznit XML Catalogs se mi nepodařilo. Nicméně stále je zpracování DTD velmi pomalé – asi 50× prodlouží načtení XHTML souboru.

    Mnohem rychlejší je preprocesing vstupního souboru
    nahradit atribut id za xml:id
    nahradit jmenné entity za číselné

    a pak parsovat bez DTD.

    před 9 lety
  4. marek http://www.bikenews.cz #4

    avatar

    nevadí že napíšu komentář k nečlánku? :) Co vedlo k napsání komentáře o nečlánku po osmi hodinách od napsání?

    před 9 lety | reagoval [5] David Grudl
  5. David Grudl http://davidgrudl.com #5

    avatar

    #4 marku, to je pozůstatek jednoho smazaného komentáře a smazaných reakcí na to, že jsem jej smazal ;-)

    před 9 lety
  6. xom http://pinion.xom-tom.com #6

    avatar

    Děkuju za souhrn, velice se to hodí, zvláště, když přemýšlím nad tvorbou PHP OpenXML docx generátoru, který jsem po netu hledal a nějak nenašel – pokud byste někdo o tom generátoru věděl, tak napište, ať nedělám zbytečnou práci (pro tabulkový Excel již existuje PHP Excel

    před 9 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.