Viewed   344 times

I build a script that combines all css on a page together to use it in my cms. It worked fine for a long time now i i get this error:


Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: Tag header invalid in Entity, line: 10 in css.php on line 26

Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: Tag nav invalid in Entity, line: 10 in css.php on line 26

Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: Tag section invalid in Entity, line: 22 in css.php on line 26

This is the php script

This is my code:

<?php
header('Content-type: text/css');
include ('../global.php');

if ($usetpl == '1') {
    $client = New client();
    $tplname = $client->template();
    $location = "../templates/$tplname/header.php";
    $page = file_get_contents($location);
} else {
    $page = file_get_contents('../index.php');
}

class StyleSheets extends DOMDocument implements IteratorAggregate
{

    public function __construct ($source)
    {
        parent::__construct();
        $this->loadHTML($source);
    }

    public function getIterator ()
    {
        static $array;
        if (NULL === $array) {
            $xp = new DOMXPath($this);
            $expression = '//head/link[@rel="stylesheet"]/@href';
            $array = array();
            foreach ($xp->query($expression) as $node)
                $array[] = $node->nodeValue;
        }
        return new ArrayIterator($array);
    }
}

foreach (new StyleSheets($page) as $index => $file) {
    $css = file_get_contents($file);
    echo $css;
}

 Answers

1

Header, Nav and Section are elements from HTML5. Because HTML5 developers felt it is too difficult to remember Public and System Identifiers, the DocType declaration is just:

<!DOCTYPE html>

In other words, there is no DTD to check, which will make DOM use the HTML4 Transitional DTD and that doesnt contain those elements, hence the Warnings.

To surpress the Warnings, put

libxml_use_internal_errors(true);

before the call to loadHTML and

libxml_use_internal_errors(false);

after it.

An alternative would be to use https://github.com/html5lib/html5lib-php.

Tuesday, August 23, 2022
2

Simple Answer: You can't. See the manual:

The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

For every other error, you can use set_error_handler()

EDIT:

Since it seems, that there are some discussions on this topic, with regards to using register_shutdown_function, we should take a look at the definition of handling: To me, handling an error means catching the error and reacting in a way that is "nice" for the user and the underlying data (databases, files, web services, etc.).

Using register_shutdown_function you cannot handle an error from within the code where it was called, meaning the code would still stop working at the point where the error occurs. You can, however, present the user with an error message instead of a white page, but you cannot, for example, roll back anything that your code did prior to failing.

Tuesday, August 30, 2022
2

If you want to get :

  • The text
  • that's inside a <div> tag with class="text"
  • that's, itself, inside a <div> with class="main"

I would say the easiest way is not to use DOMDocument::getElementsByTagName -- which will return all tags that have a specific name (while you only want some of them).

Instead, I would use an XPath query on your document, using the DOMXpath class.


For example, something like this should do, to load the HTML string into a DOM object, and instance the DOMXpath class :

$html = <<<HTML
<div class="main">
    <div class="text">
    Capture this text 1
    </div>
</div>

<div class="main">
    <div class="text">
    Capture this text 2
    </div>
</div>
HTML;

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

$xpath = new DOMXPath($dom);


And, then, you can use XPath queries, with the DOMXPath::query method, that returns the list of elements you were searching for :

$tags = $xpath->query('//div[@class="main"]/div[@class="text"]');
foreach ($tags as $tag) {
    var_dump(trim($tag->nodeValue));
}


And executing this gives me the following output :

string 'Capture this text 1' (length=19)
string 'Capture this text 2' (length=19)
Monday, December 5, 2022
3

The Manual explains why:

For this function to work, you will need either to set some ID attributes with DOMElement->setIdAttribute() or a DTD which defines an attribute to be of type ID. In the later case, you will need to validate your document with DOMDocument->validate() or DOMDocument->validateOnParse before using this function.

By all means, go for valid HTML & provide a DTD.

Quick fixes:

  1. Call $dom->validate(); and put up with the errors (or fix them), afterwards you can use $dom->getElementById(), regardless of the errors for some reason.
  2. Use XPath if you don't feel like validing: $x = new DOMXPath($dom); $el = $x->query("//*[@id='bid']")->item(0);
  3. Come to think of it: if you just set validateOnParse to true before loading the HTML, if would also work ;P

.

$dom = new DOMDocument();
$html ='<html>
<body>Hello <b id="bid">World</b>.</body>
</html>';
$dom->validateOnParse = true; //<!-- this first
$dom->loadHTML($html);        //'cause 'load' == 'parse

$dom->preserveWhiteSpace = false;

$belement = $dom->getElementById("bid");
echo $belement->nodeValue;

Outputs 'World' here.

Tuesday, December 27, 2022
3

I just had a similar problem, on Rails 3.2. If you're not using Rails trunk (working towards 4.0), it doesn't understand the hstore natively - you need to define a serialization coder (which is provided by the activerecord-postgres-hstore gem), like so:

class Example < ActiveRecord::Base
  serialize :data, ActiveRecord::Coders::Hstore
end
Thursday, November 10, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :