PHP Classes

File: README.php

Recommend this page to a friend!
  Classes of Michael A. Peters   docType   README.php   Download  
File: README.php
Role: Auxiliary script
Content type: text/plain
Description: README file
Class: docType
Create HTML or XHTML depending on the user browser
Author: By
Last change:
Date: 14 years ago
Size: 19,517 bytes
 

Contents

Class file image Download
<?php require_once('xml_doctype.inc'); function addCss($dom,$head,$stylesheet) { $xmlStyle = $dom->createElement('link'); $xmlStyle->setAttribute('href',$stylesheet); $xmlStyle->setAttribute('type','text/css'); $xmlStyle->setAttribute('rel','stylesheet'); $head->appendChild($xmlStyle); } function appendLink($dom,$parent,$href,$string,$title='') { $xmlLink = $dom->createElement('a',$string); $xmlLink->setAttribute('href',$href); if (strlen($title) > 0) { $xmlLink->setAttribute('title',$title); } $parent->appendChild($xmlLink); } function navMenu($dom,$parent,$topNavMenu,$id,$string) { $anchor = $dom->createElement('a','&#160;'); $anchor->setAttribute('id',$id); $parent->appendChild($anchor); $navItem = $dom->createElement('li'); $navLink = appendLink($dom,$navItem,'#' . $id,$string); $topNavMenu->appendChild($navItem); } function addSpan($dom,$parent,$string,$class='',$style='') { $xmlSpan = $dom->createElement('span',$string); if (strlen($class) > 0) { $xmlSpan->setAttribute('class',$class); } if (strlen($style) > 0) { $xmlSpan->setAttribute('style',$style); } $parent->appendChild($xmlSpan); } function addText($dom,$parent,$string) { $xmlText = $dom->createTextNode($string); $parent->appendChild($xmlText); } function codeBlock($dom,$parent,$myArray) { $xmlPre = $dom->createElement('pre'); $xmlPre->setAttribute('class','code'); for ($i=0;$i<sizeof($myArray);$i++) { addText($dom,$xmlPre,$myArray[$i]); if ($i < (sizeof($myArray) - 1)) { $xmlBr = $dom->createElement('br'); $xmlPre->appendChild($xmlBr); } } $parent->appendChild($xmlPre); } $dom = new DOMDocument('1.0','UTF-8'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $myPage = new docType($dom); // below would force html // $myPage = new docType($dom,'text/html'); // below would force xhtml // $myPage = new docType($dom,'application/xhtml+xml'); $xmlHtml = $myPage->document(); // initiate navigation menu $topNavMenu = $dom->createElement('ul'); $xmlBody = $dom->createElement('body'); $xmlDiv = $dom->createElement('div'); $xmlDiv->setAttribute('id','pagenav'); $xmlDiv->appendChild($topNavMenu); $xmlBody->appendChild($xmlDiv); $contentDiv = $dom->createElement('div'); $xmlBody->appendChild($contentDiv); navMenu($dom,$contentDiv,$topNavMenu,'intro','Introduction'); $xmlHeader = $dom->createElement('h1','The docType Class'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','This class is for people who want to use the php '); appendLink($dom,$xmlPar,'http://php.net/manual/en/class.domdocument.php','DOMDocument'); addText($dom,$xmlPar,' class to create valid XHTML documents sent with the proper mime type while still providing backwards compatibility for users with web browsers that do not properly support the '); addSpan($dom,$xmlPar,'application/xhtml+xml','mono'); addText($dom,$xmlPar,' mime type.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','Using DOMDocument to generate your content is a little more tedious than typing content directly, but there are a lot of benefits. I will not go into a lot of detail here on the benefits, they are discussed on the php list from time to time, but to highlight:'); $contentDiv->appendChild($xmlPar); $xmlList = $dom->createElement('ul'); $xmlItem = $dom->createElement('li','XSS injection is a little easier to prevent since pages constructed with DOMDocument must be well formed.'); $xmlList->appendChild($xmlItem); $xmlItem = $dom->createElement('li','Since the page is an object and not sent until it is fully constructed, the page can be manipulated making it is easy to do things like dynamically add to the navigation menu, add JavaScript and CSS references to the document head section after you have started creating the body content, etc. This makes web applications that produce dynamic content a little bit easier to work with. While this page is not really dynamic content, view the source to get an idea of navigation menu generation while the page is being constructed.'); $xmlList->appendChild($xmlItem); $xmlItem = $dom->createElement('li','It is easier for some external applications to properly parse your web page, especially if your content includes multibyte UTF-8 characters. Some document import tools poorly handle UTF-8 from HTML but handle it quite well when coming from XML.'); $xmlList->appendChild($xmlItem); $contentDiv->appendChild($xmlList); $xmlPar = $dom->createElement('p','The class uses the '); addSpan($dom,$xmlPar,'$_SERVER[\'HTTP_ACCEPT\']','mono'); addText($dom,$xmlPar,' variable, sent by the requesting web client, to detect how well the client supports XHTML. When support is sufficient, it sets up the DOM as an XHTML document. Otherwise, it sets up the DOM as an HTML document.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','When you are ready to serve the document, the class can send the appropriate header and the appropriate version of the content.'); $contentDiv->appendChild($xmlPar); navMenu($dom,$contentDiv,$topNavMenu,'init','Initialize'); $xmlHeader = $dom->createElement('h2','Initialize the Class'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','The class needs a DOMDocument object to work with. It should be a freshly created DOMDocument object that is empty:'); $phpCode = Array('<?php'); $phpCode[] = 'require_once(\'xml_doctype.inc\');'; $phpCode[] = '$dom = new DOMDocument(\'1.0\',\'UTF-8\');'; $phpCode[] = '$dom->preserveWhiteSpace = false;'; $phpCode[] = '$dom->formatOutput = true;'; $phpCode[] = ''; $phpCode[] = '$myPage = new docType($dom);'; $phpCode[] = '$xmlHtml = $myPage->document();'; $phpCode[] = '?>'; codeBlock($dom,$contentDiv,$phpCode); $xmlPar = $dom->createElement('p','The variable '); addSpan($dom,$xmlPar,'$xmlHtml','mono'); addText($dom,$xmlPar,' represents the '); addSpan($dom,$xmlPar,'<html></html>','mono'); addText($dom,$xmlPar,' node of your document. Add your child elements to that node.'); $contentDiv->appendChild($xmlPar); navMenu($dom,$contentDiv,$topNavMenu,'serve','Serving'); $xmlHeader = $dom->createElement('h2','Serving the Content'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Once your document is fully constructed and you are ready to serve it:'); $contentDiv->appendChild($xmlPar); $phpCode = Array('<?php'); $phpCode[] = '$myPage->sendheader();'; $phpCode[] = '// any other headers you want to send, such as cache instructions or CSP headers'; $phpCode[] = '$myPage->sendpage();'; $phpCode[] = '?>'; codeBlock($dom,$contentDiv,$phpCode); $xmlPar = $dom->createElement('p','That’s it! Your content has now been served. Browsers that properly support the '); addSpan($dom,$xmlPar,'application/xhtml+xml','mono'); addText($dom,$xmlPar,' mime type will get an XHTML version of your page. Other browsers will get an HTML version of your page.'); $contentDiv->appendChild($xmlPar); navMenu($dom,$contentDiv,$topNavMenu,'pvar','Public Variables'); $xmlHeader = $dom->createElement('h2','Public Variables'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Public variables need to be defined after the class is initialized. All except for the last one must be defined before the '); addSpan($dom,$xmlPar,'document()','mono'); addText($dom,$xmlPar,' function is called. You can also extend the class the define them.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','$htmlDT'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','The DOCTYPE string to use for HTML documents. Defaults to HTML 4.01 strict.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','$xhtmlDT'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','The DOCTYPE string to use for XHTML documents. Defaults to XHTML 1.1.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','$xmlLang'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','The '); addSpan($dom,$xmlPar,'xml:lang','mono'); addText($dom,$xmlPar,' attribute to use for XHTML documents. Defaults to '); addSpan($dom,$xmlPar,'en','mono'); addText($dom,$xmlPar,'.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','$noChild'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Array. In (X)HTML, some elements are never allowed to have child elements. For example, the '); addSpan($dom,$xmlPar,'meta','mono'); addText($dom,$xmlPar,' element may never have any child elements.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','In XHTML these elements are always self closing and there is no problem. However, current versions of standards compliant HTML do not use self closing tags and a closing tag is technically not valid for these elements as it results in an child, even if that child is 0 bytes. DOMDocument knows about most of these and will not create a closing element for them when dumping the DOM to HTML, but it does not know about some of the new ones introduced with HTML 5.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','If you use any of these newer elements and you want your page to be technically correct, you can define them in the '); addSpan($dom,$xmlPar,'$noChild','mono'); addText($dom,$xmlPar,' array and the incorrect closing tags will be removed from HTML content before it is sent. You do not need to define this public variable until you are ready to use the '); addSpan($dom,$xmlPar,'sendpage()','mono'); addText($dom,$xmlPar,' function.'); $contentDiv->appendChild($xmlPar); navMenu($dom,$contentDiv,$topNavMenu,'func','Public Functions'); $xmlHeader = $dom->createElement('h2','Public Functions'); $contentDiv->appendChild($xmlHeader); $xmlHeader = $dom->createElement('h3','docType($dom,$accept=\'\')'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Constructor function. Takes a DOMDocument object as the first argument, optional an accept string for the second argument (overrides what the browser sends, useful for debugging or forcing HTML). This function is called when you initialize the class.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','document()'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Loads the Document Type and root element into the DOM object.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','sendheader()'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Sends the header telling the client what kind of document it is going to receive.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','sendpage()'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Sends the web page to the requesting client.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','generator()'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Optional. Creates a '); addSpan($dom,$xmlPar,'meta','mono'); addText($dom,$xmlPar,' generator tag specifying version of libxml2 your php build was compiled against. The output would be used as a child of the document header. For example:'); $contentDiv->appendChild($xmlPar); $phpCode = Array('<?php'); $phpCode[] = '$xmlHead = $dom->createElement(\'head\');'; $phpCode[] = '$generator = $myPage->generator();'; $phpCode[] = '$xmlHead->appendChild($generator);'; $phpCode[] = '?>'; codeBlock($dom,$contentDiv,$phpCode); navMenu($dom,$contentDiv,$topNavMenu,'gotcha','Gotchas'); $xmlHeader = $dom->createElement('h2','Gotchas'); $contentDiv->appendChild($xmlHeader); $xmlHeader = $dom->createElement('h3','White Space'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Make sure you do not have any blank lines or carriage returns before your opening '); addSpan($dom,$xmlPar,'<?php','mono'); addText($dom,$xmlPar,'. Otherwise the server may send a header and content before you intend it to, which will result in a broken page.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','Lower Case Elements'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','HTML is not case sensitive for element and attribute names. XML is, and XHTML uses lower case for element and attribute names. When you create elements and attributes, make sure they are lower case.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','HTML Entities'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','HTML defines many entities that are popular in web design. For example, '); addSpan($dom,$xmlPar,'&amp;nbsp;','mono'); addText($dom,$xmlPar,' and '); addSpan($dom,$xmlPar,'&amp;copy;','mono'); addText($dom,$xmlPar,'.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','These are not valid in XML unless defined in the Document Type. Do not use them, they will cause DOMDocument errors before the page is even sent. You should use the '); appendLink($dom,$xmlPar,'http://www.w3schools.com/tags/ref_entities.asp','Entity Number'); addText($dom,$xmlPar,' instead. For a non breaking space, you would use '); addSpan($dom,$xmlPar,'&amp;#160;','mono'); addText($dom,$xmlPar,'. For copyright symbol, you could use either '); addSpan($dom,$xmlPar,'&amp;#169;','mono'); addText($dom,$xmlPar,' or use a UTF-8 text editor and just type a © directly.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','JavaScript'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','Inline JavaScript is bad form. You really should keep your JavaScript external and reference in your document head. However, even though it is bad form, it technically is legal to define your scripts inline.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','If you insist on using inline JavaScript, you need to be aware that XHTML does not play nice with JavaScript contained in a comment. It needs to be contained in a '); appendLink($dom,$xmlPar,'http://www.w3schools.com/xmL/xml_cdata.asp','cdata'); addText($dom,$xmlPar,' block. Note that this will cause it to fail in some older browsers, you really should just keep all your JavaScript external, it really is the best way.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','Additionally, the JavaScript '); addSpan($dom,$xmlPar,'document.write()','mono'); addText($dom,$xmlPar,' function can not be used with XHTML. If you have JavaScript that modifies the document, use the '); appendLink($dom,$xmlPar,'http://developer.apple.com/internet/webcontent/dom2i.html','DOM2'); addText($dom,$xmlPar,' functions.'); $contentDiv->appendChild($xmlPar); navMenu($dom,$contentDiv,$topNavMenu,'tips','Tips'); $xmlHeader = $dom->createElement('h2','Tips and Tricks'); $contentDiv->appendChild($xmlHeader); $xmlHeader = $dom->createElement('h3','Static Content'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','When creating documents from scratch with DOMDocument, it can be a lot more tedious than just typing the raw HTML. Look at the source of this page to see just how tedious it can be.'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','You can still create your content the old way, you just need to write it as vanilla XML and then import it into your document. For example, suppose you have a text file called \''); addSpan($dom,$xmlPar,'content.xml','mono'); addText($dom,$xmlPar,'\' containing the following:'); $contentDiv->appendChild($xmlPar); $xmlCode = Array('<?xml version="1.0" encoding="UTF-8"?>'); $xmlCode[] = '<body>'; $xmlCode[] = '<h1 class="funky">Hello World!</h1>'; $xmlCode[] = '<p style="text-align: center;">I am a paragraph<br />'; $xmlCode[] = 'with a self closing break <span style="color: red; font-family: monospace;">'; $xmlCode[] = 'and a span</span>.</p>'; $xmlCode[] = '</body>'; codeBlock($dom,$contentDiv,$xmlCode); $xmlPar = $dom->createElement('p','Since it is clean XML, you can import that XML into your DOM using the following technique:'); $contentDiv->appendChild($xmlPar); $phpCode = Array('<php'); $phpCode[] = 'require_once(\'xml_doctype.inc\');'; $phpCode[] = '$dom = new DOMDocument(\'1.0\',\'UTF-8\');'; $phpCode[] = '$dom->preserveWhiteSpace = false;'; $phpCode[] = '$dom->formatOutput = true;'; $phpCode[] = ''; $phpCode[] = '$myPage = new docType($dom);'; $phpCode[] = '$xmlHtml = $myPage->document();'; $phpCode[] = ''; $phpCode[] = '$xmlHead = $dom->createElement(\'head\');'; $phpCode[] = '$xmlTitle = $dom->createElement(\'title\',\'I Am a Web Page\');'; $phpCode[] = '$xmlHead->appendChild($xmlTitle);'; $phpCode[] = '$xmlHtml->appendChild($xmlHead);'; $phpCode[] = ''; $phpCode[] = '$xmlfile = \'content.xml\';'; $phpCode[] = '$buffer = file_get_contents($xmlfile);'; $phpCode[] = '$tmpDOM = new DOMDocument(\'1.0\',\'utf-8\');'; $phpCode[] = '$tmpDOM->loadXML($buffer);'; $phpCode[] = '$nodeList = $tmpDOM->getElementsByTagName(\'body\');'; $phpCode[] = '$impBody = $nodeList->item(0);'; $phpCode[] = '$contentDiv = $dom->importNode($impBody,true);'; $phpCode[] = '$xmlHtml->appendChild($contentDiv);'; $phpCode[] = ''; $phpCode[] = '$myPage->sendheader();'; $phpCode[] = '$myPage->sendpage();'; $phpCode[] = '?>'; codeBlock($dom,$contentDiv,$phpCode); $xmlPar = $dom->createElement('p','The result can be seen here: '); appendLink($dom,$xmlPar,'example.php','example.php'); addText($dom,$xmlPar,'. Try viewing the generated source in a browser that properly supports XML (like Firefox) and then in a browser that does not (like Internet Explorer).'); $contentDiv->appendChild($xmlPar); $xmlPar = $dom->createElement('p','Now you can edit '); addSpan($dom,$xmlPar,'content.xml','mono'); addText($dom,$xmlPar,' at your leisure, just make sure you keep the XML well formed. DOMDocument also has a '); addSpan($dom,$xmlPar,'loadHTML()','mono'); addText($dom,$xmlPar,' function that is a little more lenient, but I do not recommend using it. It tends to replace UTF-8 multibyte characters with entities, and that causes problems. So stick with '); addSpan($dom,$xmlPar,'loadXML()','mono'); addText($dom,$xmlPar,' and keep your content as well formed XML.'); $contentDiv->appendChild($xmlPar); $xmlHeader = $dom->createElement('h3','Dynamic Content'); $contentDiv->appendChild($xmlHeader); $xmlPar = $dom->createElement('p','For dynamic content, life will be a lot easier if you write yourself a library of functions and classes to do the dirty work for you. For examples, see the functions in the php source of this file. For an example class, see my '); appendLink($dom,$xmlPar,'http://www.phpclasses.org/browse/package/5857.html','Embed Media'); addText($dom,$xmlPar,' class.'); $contentDiv->appendChild($xmlPar); // make head section $xmlHead = $dom->createElement('head'); $generator = $myPage->generator(); $xmlHead->appendChild($generator); addCss($dom,$xmlHead,'style.css'); $xmlTitle = $dom->createElement('title','The docType Class'); $xmlHead->appendChild($xmlTitle); // append head and body $xmlHtml->appendChild($xmlHead); $xmlHtml->appendChild($xmlBody); // now server it $myPage->sendheader(); $myPage->sendpage(); ?>