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