Copyright: 2009-2016 Bastian Feder, Thomas Weinert
Licence: The MIT License
FluentDOM provides an easy to use fluent interface for DOMDocument. We tried to keep the jQuery API but adapted it to PHP and the server environment.
The idea was born in a workshop of Tobias Schlitt (http://schlitt.info) about the PHP XML extensions at the IPC Spring in Berlin. He used this idea to show XPath samples in the session. Since then he contributed several ideas and hints. The basic loader concept was his idea, too.
FluentDOM is a test driven project. We write tests before and during the development. You will find the PHPUnit test in the "tests" subdirectory.
Version 5 was a complete rewrite. It is updated to the new PHP 5.4 syntax. It now provides classes that extend PHPs DOMDocument. Another focus was XML namespace support for document creation.
Version 6 bumps the minimum required PHP version to 5.6. Mostly to make use of the variadics syntax.
- Support
- Requirements
- Packagist
- Usage
- jQuery Similarities & Differences
- Backwards Compatibility Breaks
$document = FluentDOM::load(
$htmlFile,
'text/html',
[FluentDOM\Loader\Options::ALLOW_FILE => TRUE]
);
foreach ($document('//a[@href]') as $a) {
$links[] = [
'caption' => (string)$a,
'href' => $a['href']
];
}
var_dump($links);
$_ = FluentDOM::create();
$_->formatOutput = TRUE;
echo $_(
'select',
['name' => 'example'],
$_->each(
['One', 'Two', 'Three'],
function($text, $index) use ($_) {
return $_('option', ['value' => $index], $text);
}
)
)->document->saveHTML();
The wiki provides information and usage examples.
If you find a bug or have a feature request please report it in the issue tracker.
Be ware that the release packages (downloads) do not include the examples or tests. They are not needed to use the library. If you clone the repository, they will be included.
If you find a bug that has security implications, you can send an email directly to [email protected]
.
- PHP >= 5.6
- ext/dom
FluentDOM needs at least PHP 5.6 and the DOM extension. For some features additional extensions might be needed, like ext/json to load JSON strings.
FluentDOM 5.2 and later requires HHVM 3.5.
FluentDOM 4.0 to 5.1 work with HHVM 3.3 but it was limited. If you like to use HHVM it is strongly suggest to use newer releases.
FluentDOM is available on Packagist.org, just add the dependency to your composer.json.
{
"require" : {
"fluentdom/fluentdom": "^6.0"
}
}
To use CSS selectors, you need a CSS to XPath library.
Here is a new interface FluentDOM\Xpath\Transformer
which is implemented in
separate connector packages. Two are currently available.
The packages provide a fluentdom/css-selector
meta package.
Had fixed support for two CSS to XPath libraries. If they are installed in the project CSS selects are available.
The examples load the sample.xml file, look for tags <h1> with the attribute "id" that has the value "title", set the content of these tags to "Hello World" and output the manipulated document.
Using the FluentDOM\Document
class:
<?php
$fd = FluentDOM::load('sample.xml');
foreach ($fd('//h1[@id = "title"]') as $node) {
$node->nodeValue = 'Hello World!';
}
echo $fd->saveXml();
Using the FluentDOM\Query
class:
<?php
echo FluentDOM('sample.xml')
->find('//h1[@id = "title"]')
->text('Hello World!');
If you install a CSS selector to Xpath translation library into a project,
you can use the FluentDOM::QueryCss()
function. It returns a FluentDOM\Query
instance
supporting CSS 3 selectors.
<?php
$fd = FluentDOM::QueryCss('sample.xml')
->find('h1#title')
->text('Hello World!');
New features in FluentDOM make it easy to create XML, even XML with namespaces. Basically
you can register XML namespaces on the document and methods without direct namespace support
(like createElement()
) will resolve the namespace and call the namespace aware variant
(like createElementNS()
).
Check the Wiki for an example.
FluentDOM was created after the jQuery API and concepts. You will notice that the most method names and parameters are the same.
Many thanks to the jQuery (jquery.com) people for their work, who did an exceptional job describing their interfaces and providing examples. This saved us a lot of work. We implemented most of the jQuery methods into FluentDOM
To be able to write PHPUnit Tests and develop FluentDOM a lot of examples were written. Most of them are copied and adapted from or are deeply inspired by the jQuery documentation. They are located in the 'examples' folder. Once again many thanks to the jQuery team.
By default every method that supports a selector uses XPath not CSS selectors. Since XPath is supported by the ext/dom extension, no extra parsing need to be done. This should be faster processing the selectors and was easier to implement.
But FluentDOM can use CSS selectors with the help of a converter library.
With a few exceptions FluentDOM handles text nodes just like element nodes. You can select, traverse and manipulate them.
FluentDOM provides extended variants of some of the DOM classes. Most of it is dedicated to improve namespace handling, some works around known problems and some is just for comfort.
You can register namespaces on the document. They will be used if elements or attributes are created/updated and no explicit namespace is provided. You can even register a default namespace for elements.
The minimum required PHP version now is 5.6.
FluentDOM\Query
now parses fragment arguments depending on the
content type. It uses the loaders to parse the fragments for methods like
FluentDOM\Query::append()
. To parse the fragments as XML change the content type
after loading.
$fd = FluentDOM($content, 'type/some-type');
$fd->contentType = 'text/xml';
FluentDOM\Query::attr()
, FluentDOM\Query::css()
and FluentDOM\Query::data()
now recognize that the second argument is provided, even if it is NULL.
Serializer factories can now be registered on the FluentDOM class. Loaders implement
an additional method to parse a fragment. This allows the FluentDOM\Nodes() class
to keep the content type used to load a source. Methods like append()
now parse
a string as a fragment of the current content type. Casting the FluentDOM\Nodes()
instance to a string serializes it to the current content type.
$fd = FluentDOM('{"firstName": "John"}', 'text/json');
echo $fd->find('/*')->append('{"lastName": "Smith"}');
/*
{"firstName":"John","lastName":"Smith"}
*/
To get the previous behaviour you will have to change the content type to 'text/xml' after loading a source.
$fd = FluentDOM('{"firstName": "John"}', 'text/json');
$fd->contentType = 'text/xml';
echo $fd->find('/*')->append('<lastName>Smith</lastName>');
/*
<json:json xmlns:json="urn:carica-json-dom.2013">
<firstName>John</firstName>
<lastName>Smith</lastName>
</json:json>
*/
Loaders have an additional method loadFragment(). Serializers are now expected to be able to serialize a node (not only a document).
You will now have to explicitly allow loaders to load a file.
$fd = FluentDOM('...', '...', [FluentDOM\Loader\Options::ALLOW_FILE => TRUE]);
$fd = FluentDOM('...', '...', [FluentDOM\Loader\Options::IS_FILE => TRUE]);
CSS Selectors are now provided by separate packages. If you like to use them you will need to require the connector package now.
The FluentDOM\Loadable::load()
method now has a third argument $options. The
FluentDOM\Nodes method and the FluentDOM function that load data sources got this
argument, too. It allows to specify additional, loader specific options. The
values are only used inside the loader. This change affects the implementation of
loaders, but not the use.
Version 5 is a major rewrite. It now uses php namespaces. The original FluentDOM
classes (FluentDOM
, FluentDOMCore
and FluentDOMStyle
) are merged into the new
FluentDOM\Query
class.
The old loaders are gone and replaced with the new FluentDOM\Loadable interface.
The registerNamespaces() method was replaced with a registerNamespace() method, having the same arguments like DOMXpath::registerNamespace().