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
- ponechat nastavené
- 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:
- rozezná jen číselné entity a
< > & " - je problém s getElementById() (řeší workaround nebo DOMElement->setIdAttributeNode())
- rozezná jen číselné entity a
$dom->encodingurč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
formatOutputlze povolit jen tehdy, pokud bylo načítáno spreserveWhiteSpace == FALSEsaveXML($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->encodingnastaví na NULL a už nepůjde změnit při ukládání - přepisuje
\rna → 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 » přidat
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře ani hlasovat
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.
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ě?
[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.idzaxml:ida pak parsovat bez DTD.
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í?
[4] marek: to je pozůstatek jednoho smazaného komentáře a smazaných reakcí na to, že jsem jej smazal
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
Podle čeho DOM určuje typ node? Já se přes něj snažil naimportovat jednoduché XML typu:
a smůla. Proste NODE „types“ se rozhodl považovat za DOMText a nešel tím pádem listovat přes ChildNodes
[7] pavel: klasika, chyba mezi židlí a klávesnicí :)
Dal jsem si tu práci a dohledal to (je to dávno přepsáno do simpleXML) a byla tam triviální bota v zaměření NODE
Ahoj mám takovej nepěknej problém, a to mám nasledující kód(který z jednoho dokumentu vezme element a přepíše jim element se stejným id v jiném dokumentu).
Element se přepíše, bohužel ho pak nelze získat pomocí getElementById a jeho potomky taky ne. Nevíte jak toto obejít je to snad omezení atributu xml:id místo id?
Očekávaný výsledek:
childAvšak výsledek je:
parent