Skip to content

Typo in error message: Dom\NO_DEFAULT_NS instead of Dom\HTML_NO_DEFAULT_NS #17609

Closed

Description

@momala454

Description

The following code:

<?php
try {
    \Dom\HTMLDocument::createFromString('', options: LIBXML_HTML_NODEFDTD);
} catch (\Throwable $e) {
    echo $e->__toString();
}
\Dom\HTMLDocument::createFromString('', options: Dom\NO_DEFAULT_NS);

https://3v4l.org/pZj10/rfc#vgit.master

Resulted in this output:

ValueError: Dom\HTMLDocument::createFromString(): Argument #2 ($options) contains invalid flags (allowed flags: LIBXML_NOERROR, LIBXML_COMPACT, LIBXML_HTML_NOIMPLIED, Dom\NO_DEFAULT_NS) in /in/pZj10:4
Stack trace:
#0 /in/pZj10(4): Dom\HTMLDocument::createFromString('', 4)
#1 {main}
Fatal error: Uncaught Error: Undefined constant "Dom\NO_DEFAULT_NS" in /in/pZj10:8

But I expected this output instead:

ValueError: Dom\HTMLDocument::createFromString(): Argument #2 ($options) contains invalid flags (allowed flags: LIBXML_NOERROR, LIBXML_COMPACT, LIBXML_HTML_NOIMPLIED, Dom\HTML_NO_DEFAULT_NS) in /in/pZj10:4
Stack trace:
#0 /in/pZj10(4): Dom\HTMLDocument::createFromString('', 4)
#1 {main}
Fatal error: Uncaught Error: Undefined constant "Dom\NO_DEFAULT_NS" in /in/pZj10:8

The name is HTML_NO_DEFAULT_NS and not NO_DEFAULT_NS

By the way, as LIBXML_HTML_NODEFDTD does not work with \Dom\HtmlDocument, we need to use \Dom\HTML_NO_DEFAULT_NS, and when using that option, void tags are considered as not void and <br> is converted to <br></br>. I don't know if it's expected, and I don't know what to do to prevent this when trying to get an output without added doctype when one isn't provided.
Should I make another issue ?

var_dump(\Dom\HTMLDocument::createFromString('<!DOCTYPE html>
<html>
<body>abc<br>def</body></html>', options: \Dom\HTML_NO_DEFAULT_NS)->saveHtml());

Output

<!DOCTYPE html><html><head></head><body>abc<br></br>def</body></html>

https://3v4l.org/UJ8fL/rfc#vgit.master

Edit: the goal is to not add a doctype here:

$html = 'abc<br>def';
var_dump(\Dom\HTMLDocument::createFromString($html, options: LIBXML_NOERROR|\Dom\HTML_NO_DEFAULT_NS)->saveHtml());

$dom = new \DOMDocument(encoding: 'UTF-8');
$dom->loadHTML($html, LIBXML_NOERROR| LIBXML_HTML_NODEFDTD);
var_dump($dom->saveHtml());

Output :

string(54) "<html><head></head><body>abc<br></br>def</body></html>"
string(44) "<html><body><p>abc<br>def</p></body></html>
"

https://3v4l.org/AuPs9/rfc#vgit.master

edit2: i notice that I can use LIBXML_HTML_NOIMPLIED instead of \Dom\HTML_NO_DEFAULT_NS, but then the problem is xpath does not work https://3v4l.org/Tgm1W/rfc#vgit.master
and registering the namespace didn't helped

PHP Version

8.4.2

Operating System

No response

Activity

  1. momala454 commented on Jan 28, 2025

    @momala454
    Author

    another problem with HTML_NO_DEFAULT_NS, as it transforms <br> or </br> into <br></br>, every time I parse it again, it double the number of <br>
    https://3v4l.org/IAVTg/rfc#vgit.master

    $html = '<div>abc<br>def</div>';
    $dom = \Dom\HTMLDocument::createFromString($html, options: LIBXML_NOERROR | \Dom\HTML_NO_DEFAULT_NS/*|LIBXML_HTML_NOIMPLIED*/);
    var_dump($dom->saveHtml());
    
    $dom = \Dom\HTMLDocument::createFromString($dom->saveHtml(), options: LIBXML_NOERROR | \Dom\HTML_NO_DEFAULT_NS/*|LIBXML_HTML_NOIMPLIED*/);
    var_dump($dom->saveHtml());
    
    
    $dom = new \DOMDocument(encoding: 'UTF-8');
    $dom->loadHTML($html, LIBXML_NOERROR| LIBXML_HTML_NODEFDTD|LIBXML_HTML_NOIMPLIED);
    var_dump($dom->saveHtml());
    string(65) "<html><head></head><body><div>abc<br></br>def</div></body></html>"
    string(74) "<html><head></head><body><div>abc<br></br><br></br>def</div></body></html>"
    string(22) "<div>abc<br>def</div>
    "
    
  2. ndossche commented on Jan 28, 2025

    @ndossche
    Member

    Alright there's a lot to unpack here.

    The name is HTML_NO_DEFAULT_NS and not NO_DEFAULT_NS

    Indeed, this appears to be a typo in the error message, nice spot!

    By the way, as LIBXML_HTML_NODEFDTD does not work with \Dom\HtmlDocument

    Indeed it does not, because this is the default behaviour.
    See also https://wiki.php.net/rfc/domdocument_html5_parser#the_options_argument if you want to know the background about some of the options being left out.

    we need to use \Dom\HTML_NO_DEFAULT_NS

    I believe you misunderstand what \Dom\HTML_NO_DEFAULT_NS means. That option only really exists as a BC option. It prevents putting the elements in the HTML namespace (NS=namespace); so they won't actually be HTML elements. This has consequences to serialization and to how some properties and methods behave. Generally, if you don't know the implications already you should probably not use this.

    , and when using that option, void tags are considered as not void and <br> is converted to <br></br>. I don't know if it's expected

    Yes this is expected: whether a tag is void or not depends on its name and its namespace, but because HTML_NO_DEFAULT_NS disables using the HTML namespace, this is no longer a void tag and is therefore rendered as <br></br>.

    and I don't know what to do to prevent this when trying to get an output without added doctype when one isn't provided.

    The default behaviour is to not add a doctype when none is found, but in your example code you explicitly added <!DOCTYPE html> in the input string.
    If you want to remove a doctype from a document afterwards, you can use $dom->removeChild($dom->doctype);. This works in both the old DOM and new DOM classes.

    Edit: the goal is to not add a doctype here:

    If I remove \Dom\HTML_NO_DEFAULT_NS from the options this has the desired result and still does not include a doctype.

    edit2: i notice that I can use LIBXML_HTML_NOIMPLIED instead of \Dom\HTML_NO_DEFAULT_NS, but then the problem is xpath does not work https://3v4l.org/Tgm1W/rfc#vgit.master
    and registering the namespace didn't helped

    You not only have to register the namespace, you also need to specify the prefix in the xpath query, like so: var_dump($xpath->query('//xhtml:div')->length);.
    Also, you can just use querySelectorAll which would be simpler 🙂

    another problem with HTML_NO_DEFAULT_NS, as it transforms <br> or </br> into <br></br>, every time I parse it again, it double the number of <br>

    Why it is turned into <br></br> was already explained above. The reason it then parses it like <br><br> again is because <br></br> isn't valid HTML 5.

  3. changed the title [-]Dom\NO_DEFAULT_NS does not exist[/-] [+]Typo in error message: Dom\NO_DEFAULT_NS instead of Dom\HTML_NO_DEFAULT_NS[/+] on Jan 28, 2025
  4. added a commit that references this issue on Jan 28, 2025
    359eb30
  5. added a commit that references this issue on Jan 28, 2025
    286030d
  6. ndossche commented on Jan 28, 2025

    @ndossche
    Member

    I've pushed the fix for the typo in the error message.
    The other things you noted are not bugs; but feel free to use this thread to discuss if you still have questions.

  7. momala454 commented on Jan 28, 2025

    @momala454
    Author

    thank you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions