{"id":20727544,"url":"https://github.com/manychois/simdom","last_synced_at":"2025-09-12T21:54:42.953Z","repository":{"id":65502898,"uuid":"583912356","full_name":"manychois/simdom","owner":"manychois","description":"A simple-to-use PHP library for processing DOM documents.","archived":false,"fork":false,"pushed_at":"2025-02-24T18:17:05.000Z","size":489,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-23T19:15:02.390Z","etag":null,"topics":["dom","html","html5","parser","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/manychois.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-31T12:34:08.000Z","updated_at":"2024-11-19T07:53:13.000Z","dependencies_parsed_at":"2023-09-27T16:01:50.768Z","dependency_job_id":"1d75e32f-e6e1-47b9-8c34-23b06e6842aa","html_url":"https://github.com/manychois/simdom","commit_stats":{"total_commits":22,"total_committers":3,"mean_commits":7.333333333333333,"dds":"0.18181818181818177","last_synced_commit":"55a217395e1f6166c88483acbcfd52958ffa36ff"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manychois%2Fsimdom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manychois%2Fsimdom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manychois%2Fsimdom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manychois%2Fsimdom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/manychois","download_url":"https://codeload.github.com/manychois/simdom/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250496993,"owners_count":21440231,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dom","html","html5","parser","php"],"created_at":"2024-11-17T04:32:11.696Z","updated_at":"2025-09-12T21:54:42.936Z","avatar_url":"https://github.com/manychois.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simdom - A simplified and relaxed DOM structure library\n\n[![PHP Version](https://img.shields.io/badge/php-%3E%3D8.4-777bb3.svg)](https://www.php.net/releases/8.4/en.php)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\nSimdom is a lightweight PHP library designed to make parsing and manipulating DOM documents as straightforward as possible. It requires no external dependencies or extensions.\n\nWithout using the built-in PHP DOM extension, Simdom can have its own opinionated appraoch on how HTML documents should be parsed and manipulated. It lets you to work with \"non-compliant\" HTML structure in a literal and intuitive way.\n\nBefore outputing the HTML string of the document, you can call the `$document-\u003evalidate()` method to ensure that the document is valid according to the HTML5 specification.\n\n## Key differences from the standard HTML5 DOM specification / PHP DOM extension\n\n### Simplified node types\n\nSimdom provides 6 node types that form the DOM tree:\n\n- `Document` - The root document node\n- `Doctype` - Document type declarations\n- `Element` - HTML elements with attributes and child nodes\n- `Text` - Text content within elements\n- `Comment` - HTML comments\n- `Fragment` - Document fragments for grouping nodes\n\nAttributes are not considered as a node type in Simdom, but rather as properties of `Element` nodes.\n\nCDATA section or processing instructions are not supported, as they would not be valid in HTML5 documents.\n\n## Simplified and relaxed DOM structure\n\n- There is no concept of an owner document, meaning nodes can be freely moved between documents.\n- There is no concept of namespace.\n- `Document`, `Element` and `Fragment` nodes can have child nodes of any type except `Document` and `Fragment`, in any order, i.e.:\n  - `Document` can hold `Text` child.\n  - `Document` does not restrict at most one `Doctype` child, and it does not have to be placed before any `Element` child.\n  - `Document` does not restrict at most one `Element` child.\n  - `Element` and `Fragment` can hold `Doctype` child.\n- There is no concept of valid element structure, meaning elements can be nested in any way, even if it would not be valid HTML5, i.e. `\u003ctable\u003e\u003cul\u003e\u003c/ul\u003e\u003c/table\u003e` would be parsed as it is.\n- Misaligned end tags are fixed by finding the last matching start tag, i.e. `\u003cdiv\u003e\u003cspan\u003eabc\u003c/div\u003e` would be parsed as `\u003cdiv\u003e\u003cspan\u003eabc\u003c/span\u003e\u003c/div\u003e`. If there is no matching start tag, the end tag is ignored.\n- `\u003ctemplate\u003e` elements are treated as a Rawtext type element like `\u003cscript\u003e` or `\u003cstyle\u003e`.\n- Self-closing tag syntax is supported, for example `\u003cdiv /\u003e` is parsed as `\u003cdiv\u003e\u003c/div\u003e`.\n- All element names and attributes names are parsed as their ASCII-lowercase form.\n\n## Restrictions\n\nHowever, there are still some lines you cannot cross in Simdom:\n- `Document` and `Fragment` has no parent node, and cannot be a child of any other node. (Inserting `Fragment` as a child of any parent node is fine though, as it means inserting the `Fragment`'s child nodes.)\n- `Element` name and attribute names must conform to the HTML5 specification.\n- `Doctype` name, public identifier and system identifier must conform to the HTML5 specification.\n- `Doctype` name must be present if either public or system identifier is present.\n- No control characters are allowed anywhere, e.g. you cannot inject an delete character (U+007F) to a `Text` node.\n- `Comment` cannot contain the character sequence `--\u003e`.\n- If a `Text` node is under a Rawtext type (e.g. `\u003cscript\u003e`) or Rcdata type (e.g. `\u003ctextarea\u003e`) element, it cannot contain the character sequence which may terminate the corresponding element start tag, e.g. `\u003c/script`, or `\u003c/textarea`.\n\n\n## Getting Started\n\n### Installation\n\n```bash\ncomposer require manychois/simdom\n```\n\n## Requirements\n\n- PHP 8.4 or higher\n\n## Some Basic Usages\n\n### Parsing HTML Documents\n\n```php\nuse Manychois\\Simdom\\HtmlParser;\n\n$parser = new HtmlParser();\n$doc = $parser-\u003eparseDocument('\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003cbody\u003e\u003cp\u003eHello, world!\u003c/p\u003e\u003c/body\u003e\u003c/html\u003e');\n// $doc is an instance of \\Manychois\\Simdom\\Document\n```\n\n### Node Manipulation\n\n```php\nuse Manychois\\Simdom\\Document;\nuse Manychois\\Simdom\\Element;\n\n// Create documents\n$doc = Document::create();\n\n// Create elements\n$div = Element::create('div');\n$div-\u003esetAttr('class', 'container');\n$div-\u003eid = 'main-content';\n```\n\n### Traversing and Manipulating the DOM Tree\n\n```php\n// Access document parts\n$html = $doc-\u003edocumentElement; // The \u003chtml\u003e element\n$head = $doc-\u003ehead;           // The \u003chead\u003e element\n$body = $doc-\u003ebody;           // The \u003cbody\u003e element\n\n// Navigate the tree\n$element = $body-\u003efirstElementChild;\n$nextElement = $element-\u003enextElementSibling;\n$parent = $element-\u003eparent;\n\n// Child node access\nforeach ($body-\u003echildNodes as $node) {\n    echo get_class($node) . \"\\n\";\n}\n\n// Element-only access\nforeach ($body-\u003echildren as $element) {\n    echo $element-\u003ename . \"\\n\";\n}\n```\n\n### Adding and Removing Nodes\n\n```php\n// Append nodes\n$body-\u003eappend($div, $text);\n$body-\u003eappendChild($comment);\n\n// Prepend nodes\n$body-\u003eprepend(Text::create('First text'));\n\n// Insert before/after\n$div-\u003ebefore(Comment::create('Before div'));\n$div-\u003eafter(Text::create('After div'));\n\n// Replace nodes\n$div-\u003ereplaceWith(Element::create('section'));\n\n// Remove nodes\n$div-\u003eremove();\n```\n\n### Working with Attributes\n\n```php\n$element = Element::create('input');\n// Set attributes\n$element-\u003esetAttr('type', 'text');\n// Get attributes\n$type = $element-\u003egetAttr('type'); // 'text'\n$missing = $element-\u003egetAttr('missing'); // null\n// Check existence\n$hasType = $element-\u003ehasAttr('type'); // true\n// Remove attributes\n$element-\u003eremoveAttr('name');\n// Get all attributes\n$attrs = $element-\u003eattrs(); // ['type' =\u003e 'text']\n```\n\n### Searching and Traversal\n\n```php\n// Depth-first search\n$found = $doc-\u003edfs(fn($node) =\u003e $node instanceof Element \u0026\u0026 $node-\u003eid === 'target');\n\n// Breadth-first search\n$found = $doc-\u003ebfs(fn($node) =\u003e $node instanceof Element \u0026\u0026 $node-\u003ename === 'button');\n\n// Find the first form\n$form = $doc-\u003equerySelector('form');\n\n// Iterate through all descendants\nforeach ($doc-\u003edescendants() as $node) {\n    if ($node instanceof Text) {\n        echo $node-\u003edata . \"\\n\";\n    }\n}\n```\n\n### HTML Serialization\n\n```php\n// Convert to string representation\n$html = (string) $doc;\n// or using the __toString() method\n$html = $element-\u003e__toString();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanychois%2Fsimdom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanychois%2Fsimdom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanychois%2Fsimdom/lists"}