Jump to content

PHP DOM


djp1988

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;

Link to comment
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.

Link to comment
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 ?

Link to comment
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.

Link to comment
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 />.
Link to comment
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 "/>".

Link to comment
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.
Link to comment
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?

Link to comment
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();	}

Link to comment
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);

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...