Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Html5 Dom Document Php Laravel Package

ivopetkov/html5-dom-document-php

A PHP HTML5 DOMDocument library that parses and serializes modern HTML5 reliably while working around native DOMDocument limitations. It adds support for HTML5 tags and CSS selectors, making it easy to load, query, and manipulate documents with clean, familiar APIs.

Deep Wiki
Context7

Getting Started

composer require ivopetkov/html5-dom-document-php

There is no service provider, facade, or config file — it is a drop-in replacement for PHP's built-in DOMDocument with HTML5-aware parsing and CSS selector support. Require it and use the classes directly.

First use case — pull data out of an HTML fragment:

use IvoPetkov\HTML5DOMDocument;

$dom = new HTML5DOMDocument();
$dom->loadHTML($html);

$title = $dom->querySelector('h1.title')?->textContent;
$links = [];
foreach ($dom->querySelectorAll('article a[href^="/"]') as $a) {
    $links[] = $a->getAttribute('href');
}

Where to look first:

  1. The package README / Packagist page for the full method list.
  2. IvoPetkov\HTML5DOMDocument — the document entry point (loadHTML, querySelector, querySelectorAll, saveHTML, options constants).
  3. IvoPetkov\HTML5DOMElement — the node class (innerHTML, outerHTML, insertAdjacentHTML, getElementsByClass, querySelector*).
  4. The examples/ folder in the repo if present — it demonstrates most of the API surface in one place.

Wrap it in a small service class (e.g. App\Support\HtmlParser) rather than reaching for new HTML5DOMDocument() all over your codebase — it makes testing and swapping implementations trivial.

Implementation Patterns

Parse → DTO mapping. For scraping, keep parsing isolated from validation/serialization:

class ListingPageParser
{
    public function parse(string $html): array
    {
        $dom = new HTML5DOMDocument();
        $dom->loadHTML($html);

        return array_map(
            fn ($card) => [
                'title' => $card->querySelector('.title')?->textContent,
                'price' => $card->querySelector('.price')?->textContent,
            ],
            $dom->querySelectorAll('.listing-card')
        );
    }
}

Scraping with Laravel’s HTTP client:

$html = Http::withHeaders(['User-Agent' => config('scraper.ua')])
    ->get($url)->body();

$items = (new ListingPageParser())->parse($html);

Run scraping in a queued job and store results — parsing is cheap, network I/O isn’t.

Mutating HTML before render. Because HTML5DOMElement exposes mutable innerHTML/outerHTML, you can template content into existing markup:

$dom = new HTML5DOMDocument();
$dom->loadHTML($templateHtml);

$container = $dom->querySelector('div#content');
$container->insertAdjacentHTML('beforeend', view('partials.item', $data)->render());

return $dom->saveHTML();

This is useful for server-side injection into third-party HTML (emails, CMS snippets) where you don’t control the source.

CSS selector usage. Supported patterns cover the everyday cases: tag, #id, .class, [attr], [attr=value], [attr^=], [attr$=], [attr*=], [attr~=], descendant, >, ,, and common pseudo-classes. Keep selectors simple; if a selector silently returns nothing, fall back to getElementsByTagName() or getElementsByClass() and filter in PHP.

Extraction helpers on elements (getElementsByTagName, getElementsByClass) are faster and more predictable than complex selectors when you already have a parent node.

Sanitization pipeline. Parse with this library, then walk nodes and remove disallowed tags/attributes — but treat it as one stage of a sanitizer, not the sanitizer itself (see Gotchas). Pair it with mews/purifier or HTML Purifier for user-submitted content.

Testing. Store real HTML fixtures in tests/Fixtures/*.html, then assert against extracted arrays or against specific DOMNode properties. This is where the library shines over DOMDocument — <section>, <article>, <template>, and other HTML5 tags survive parsing intact instead of being flattened.

Octane / queued jobs. Instantiate a fresh HTML5DOMDocument per request or job; never cache parsed documents in a singleton or static property. Documents are stateful and not thread-safe.

Gotchas and Tips

  • Not a sanitizer. It parses HTML5 correctly; it does not strip XSS vectors. User-supplied HTML must still go through HTML Purifier (or equivalent) before it’s stored or rendered.

  • loadHTML() wraps fragments. Parsing "<p>Hi</p>" produces <html><body><p>Hi</p></body></html>. Call querySelector('body') and read innerHTML if you need the fragment back without wrappers.

  • Duplicate IDs. By default the library may throw on duplicate id attributes. Pass HTML5DOMDocument::ALLOW_DUPLICATE_IDS as the second argument to loadHTML() when scraping real-world pages (they almost always have duplicates).

  • Null checks are mandatory. querySelector() returns null on no match; chaining ->textContent without a null-safe operator will fatal. Use ?-> or explicit checks.

  • Suppress libxml noise. Even with HTML5 fixes, malformed input can emit warnings. Wrap parsing:

    $previous = libxml_use_internal_errors(true);
    $dom->loadHTML($html);
    libxml_clear_errors();
    libxml_use_internal_errors($previous);
    
  • Encoding. Feed UTF-8 directly — the library handles it better than raw DOMDocument, which mangles non-ASCII without a <meta charset> hint. If you see mojibake, confirm the source is actually UTF-8 before blaming the parser.

  • saveHTML() re-adds a doctype and <html>/<body>. If you only want the inner markup, extract innerHTML from <body>.

  • Memory. DOMDocument builds a full tree in memory; a 5 MB page can balloon to 30–50 MB. For large documents, chunk by section or cap input size before parsing.

  • Selector engine is a subset. :has(), :nth-of-type, and other modern pseudo-classes may not be implemented. Verify against a small fixture before relying on a selector in production.

  • Extension points. Subclass HTML5DOMDocument and HTML5DOMElement to add domain-specific helpers (e.g. toMarkdown(), plainText()), and wire the element class through the document if the library supports a customized element class — otherwise use trait-based helpers on a wrapper service.

  • FIX_MULTIPLE_TAGS option helps with pages that reuse tags incorrectly (e.g. nested <form>), but it changes the tree shape — only enable when you’ve observed a specific parsing failure.

  • No Laravel-specific tooling. No config, no facade. If you want IDE completion and container injection, write a thin HtmlParser service and bind it in a ServiceProvider; don’t wrap the whole HTML5DOMDocument API.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment