Jump to content
Sign in to follow this  
djp1988

PHP DOM

Recommended Posts

I know DOMDocument allows PHP to create the entire tree of elements in the document object model, however is there any other classes I can use to create elements on the fly, basically I'm getting frustrated with some of my code like :

$markup = '<ul>';foreach($a as $b){ $markup .= '<li>'.$b.'</li>';}$markup .= '</ul>';

I'd much rather do something like this if possible:

$dom = new SOMETHING();$ul_list = $dom->createElement('ul');foreach($a as $b){ $new_li = $dom->createElement('li'); $new_li->appendChild($dom->createTextNode($b)); $ul_list->appendChild($new_li);}echo $ul_list;

Edited by djp

Share this post


Link to post
Share on other sites

There's SimpleXML, but it has less features than DOM (for the sake of simplicity), so keep learning DOM.For your sample, assuming $b is just plain text, a proper (and learner) DOM code would look more like:

$dom = new DOMDocument();$ul_list = $dom->createElement('ul');foreach($a as $b){ $ul_list->appendChild($dom->createElement('li', $b));}$dom->appendChild($ul_list);echo $dom->saveXML();

You should keep in mind that a tree is rendered at once in a browser. If you want to render a tree gradually, similarly to what you do now, you might want to use XMLWriter instead.

Share this post


Link to post
Share on other sites

I thought DOMDocument produced an entire tree node, I've just realised that my output for it is actually only the fragment I wanted, XMLWriter looks quite good, but I am unsure about all the endElement() calls I need to make, that's becoming similar in a way to manually appending html to a string.I did find a class someone wrote for this exact problem, here's the link to that. http://davidwalsh.name/create-html-element...mlelement-classI think I will just stick to DOMDocument, for a moment I though of DOM-enizing the class on the link and naming that class DOM, that would have felt quite native !One issue I am having with DOMDocument is that it doesn't seem to be applying correct output for self-closing tags. I am trying saveXML() and saveHTML()I find this strange because a blog post I saw specifically said to use saveXML() to get self-closing tags, maybe I'm not getting this because I'm not creating an entire DOM tree of elements ? And therefore the saveXML() method doesn't have any DTD to go on ?

Edited by djp

Share this post


Link to post
Share on other sites

DOMDocument works with XML, not HTML (unless you load an existing document with loadHTMLFile(), but it's another story there). XML doesn't know which tags are self closing. Any element without contents is considered an empty element, and is serialized like one, i.e. you could have:

<ul/>

if $a was empty. It makes no difference in XML - that's still a self closing element.Also, yes, DOMDocument represents a complete XML document... as far as the DOMDocument class itself is concerned. As you've found out, you could dump the whole XML document, but at that point, PHP doesn't care that this is supposed to be a full document - it just outputs it alongside everything that has been outputted so far.But still, like I said, a DOMDocument tree is outputted at once. The reason is the tree is subject to modifications even after the appendings. You could create the full list, and then suddenly decide you must add an ID attribute to the first li element. DOM lets you do that, since it hasn't outputted anything yet. If you outputted the tree as the appendings were going on, you wouldn't be able to add that attribute after the element has been outputted.Yes, the XMLWriter approach is similar to writing out things manually, but it ensures your output is a well formed XML and safe from XSS attacks that may occur if you don't use htmlspecialchars() in a plain echo. Well... if you're using writeRaw(), only well formdness is covered for sure... I think.I'm not sure I see the idea of the class you're giving a link too. It seems like a bunch of functions that let you do what you can do with a simple XPath expression or a bunch of chained DOM calls. It would've been nice, if it wasn't so limiting.

Share this post


Link to post
Share on other sites

So to tie things up the comment made in this blog post towards the end of the article concerning self-closing tags is actually nonsense ?http://www.ultramegatech.com/blog/2009/07/...ocument-in-php/

Note: I used saveXML instead of saveHTML since XHTML documents follow some of the same standards as XML, such as self-closing tags using <tag />.
Edited by djp

Share this post


Link to post
Share on other sites

(XML < XHTML) != HTMLXHTML is based on XML, and so it follows all of its rules. Empty elements in XHTML are empty elements in XML, and are written in the same fashion. It is the reverse that's not true - An empty element in XML isn't necesarily an empty element in XHTML. Having an empty ul element is invalid for XHTML, but the document is a well formed XML even if it doesn't follow that rule.The note you're quoting is exactly correct. With saveHTML(), you'll serialize the document as HTML - elements that are empty according to HTML will be written as they are in HTML - with ">" instead of "/>". With saveXML(), elements that are empty according to XML are written as they are in XML, and any XML based language, XHTML included - with a "/>".

Share this post


Link to post
Share on other sites
The note you're quoting is exactly correct. [...] With saveXML(), elements that are empty according to XML are written as they are in XML, and any XML based language, XHTML included - with a "/>".
But I have a br element tag in my DOM, which is empty, when I call saveXML() the output is <br> and not <br /> this is the problem I'm trying to see how I can fix. Edited by djp

Share this post


Link to post
Share on other sites

Is that br element part of the DOM tree? Does it have any contents within? Where the corresponding "</br>" (saveXML() will never output "<br>" without an according "</br>"; saveHTML() would, but not saveXML())?Can you post your full code?

Share this post


Link to post
Share on other sites

Hi,It seems it is outputting <br /> but in Safari's web inspector is was showing the following:3c968e9b339f25a69e400a6cbde2ea5b.pngBut in the source code if I look at the raw code it show me:70d30e31b3aa24a98758362409f9d942.pngBut this now prompts another question, I only want the ul node and it's children, why have I got the

<?xml version="1.0"?>

tag ? Can I just get the ul node from my code ?My code is:

if(count($submenu_items) > 0){	$dom = new DOMDocument();	$ul_list = $dom->createElement('ul');	foreach($submenu_items as $b){		$li = $dom->createElement('li');		$a 	= $dom->createElement('a');		$a->setAttribute('href',$b['link']);		$a->appendChild($dom->createTextNode($b['name']));		$li->appendChild($a);				$br = $dom->createElement('br');		$li->appendChild($br);						$ul_list->appendChild($li);	}	$dom->appendChild($ul_list);	$submenu_markup = $dom->saveXML();	}

Share this post


Link to post
Share on other sites

You are writing out XML code as part of what is supposed to be an XHTML page... that XHTML page however is read as HTML by the browser, which you're of course doing for the sake of IE8 and below.That is why you are seeing a "<br>" in web dev tools - browsers parse the document (as HTML), and then serialize it for you in their view in the way they parsed it as - HTML.To remove the XML prolog, the best thing to do is to just serialize the document element, like:

$dom->saveXML($dom->documentElement);

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...