PHP and XML


We can make a PHP file that serves up straight XML; in fact, it is little more than an XML file itself.

PHP
 <?php header( "Content-Type: text/xml"); echo  '<?xml version="1.0" encoding="UTF-8"?> '; echo  '<Quiz>'; echo  '<Question>'; echo  'Einstein or Bohr:  Who got the Nobel Prize for Physics?'; echo  '<Answer score="0">Einstein</Answer>'; echo  '<Answer score="0">Bohr</Answer>'; echo  '<Answer score="1">Both</Answer>'; echo  '<Answer score="0">Neither</Answer>'; echo  '</Question>'; php?> 

Usually multiple single-line echo statements are better expressed as a single multiline echo, but there is a length limit that is exceeded by the foregoing code.

PHP
 echo  '<?xml version="1.0" encoding="UTF-8"?>        <Quiz>        <Question>        Einstein or Bohr:  Who got the Nobel Prize for Physics?        </Question>'; 

An even cleaner way to construct the file would be to remember that everything in PHP outside the tags is echoed by default and simply move all the straight XML outside the PHP tags.

PHP
 <?php  header( "Content-Type: text/xml"); ?> <?xml  version="1.0" encoding="UTF-8"      ?> <Quiz> <Question>Einstein or Bohr:  Who got the Nobel Prize for Physics?     <Answer score="0">Einstein</Answer>     <Answer score="0">Bohr</Answer>     <Answer score="1">Both</Answer>     <Answer score="0">Neither</Answer> </Question> 

Oops! We've turned our file inside out! Now it looks like an XML file with a single PHP processing instruction in it. It can be considered that way, as long as the .php file extension is left on it so that the server's PHP interpreter can find the code.

It is interesting that this file demonstrates the fact that the PHP tag is so similar to the XML declaration. Both are PI (processing instruction) codes in XML, with <?php targeting the PHP engine and <?xml targeting our XML processor.

Our data language has also matured. Note that there has been a healthy simplification of the quiz XML data structure. It now closely follows the format of the ActionScript object we recently created. This object design is terse and powerful. Question and Answer objects are defined by these constructors:

ActionScript
 function Question( questiontext, answerarray ){       this.q= questiontext;       this.a= answerarray; } function Answer( text, score, comment ){      this.text=text;      this.score=score;      this.comment=comment; } 

This leads to XML in the form of

XML
 <Quiz> <Question>question-text     <Answer score="score-value">answer-text         <Comment>comment-text</Comment></Answer>       ..more answers (at least 2 in each question)     </Question>   ..optionally more Questions (at least 1 per Quiz) </Quiz> 

We can express this structure formally in a DTD:

DTD
 QUIZ.DTD <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT Comment (#PCDATA)> <!ELEMENT Answer (#PCDATA, Comment?)> <!ATTLIST Answer score (-1  0  0.5  1) #REQUIRED > <!ELEMENT Question (#PCDATA, Answer, Answer+)> <!ELEMENT Quiz (Question+)> 

Examining it line by line we see

DTD
 <!ELEMENT Comment (#PCDATA)> 

A Comment is some text.

DTD
 <!ELEMENT Answer (#PCDATA, Comment?)> 

An Answer is also some text, with an optional Comment.

DTD
 <!ATTLIST Answer score (-1  0  0.5  1) #REQUIRED > 

An Answer must also have a score, which is either negative or positive 1, .5, or 0. These scores correspond to a set of predefined responses to the answer: wrong ( “1), right (1), partial credit (.5) or do over (0):

DTD
 <!ELEMENT Question (#PCDATA, Answer, Answer+)> 

A Question is some text and two or more Answers.

DTD
 <!ELEMENT Quiz (Question+)> 

A Quiz has at least one Question, maybe more.

According to the definition, this Nobel Prize data is a legitimate Quiz, though a pretty skimpy one (Figure 10.1). It has no Comments and only one (easy) Question. But it is well- formed XML and tested against the Quiz DTD, it is valid XML, too. It doesn't have much entertainment value, but it is an adequate example for our experiments in PHP.

Figure 10.1. Simple Quiz in an XML-Ready Browser

graphics/10fig01.jpg

PHP does more than simply echo text. PHP was created to make server scripting as easy as possible. Quite a lot of data is exposed to the script. For instance, it delivers an array of data that contains all the information about both the visitor's software and the host's server software. (The information about the remote browser was gleaned from the headers in the HTTP request that just arrived.)

$HTTP_SERVER_VARS is a predefined global variable in every PHP script. It is an associative array of variable names and their values. We can use an interesting feature of the PHP language to reliably scan through all the elements of associative arrays.

The keyword list() and the built-in function each() work together well. each() takes an array as an argument and returns a tiny array of two elements. These are the key and the value of the current element in that associative array. Every PHP array has an internal pointer and the concept of a current element. With each() the element is pointed to and then that pointer is incremented.

list() is a language keyword that looks and behaves like a function. Its arguments are a series of variables that you wish to treat as an array. Most typically list() is used to copy a known array into an ordered list of variables. That is what we will do here: We will copy simple array returned by each() as two variables. We know that this anonymous array has two members : the key and the value. So it is typical to list() them as variables like $key and $value . (For a more careful consideration of list() and each() , see the special sidebar on page 207.)

Before we can do anything with this data we need to tell the PHP script that the global variable exists. Even though it is predefined, it is not known to the PHP interpreter.

PHP
 <html> <head>  <title>Fifth PHP Code</title></head> <body> <? global $HTTP_SERVER_VARS; while (list ($key, $val) = each ($HTTP_SERVER_VARS))     echo "<b>$key</b> => $val<br>"; ?> </body></html> 

Note the HTML <b></b> tags, which set the key in boldface type, and the <br/> tag that sets line breaks. The tags help us digest the big bellyful of data we get back.

Output
  DOCUMENT_ROOT  => /home/webpages/userworld/htdocs/users/bigfun  HTTP_ACCEPT  => image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-comet, */*  HTTP_ACCEPT_ENCODING  => gzip, deflate  HTTP_ACCEPT_LANGUAGE  => en-us  HTTP_HOST  => bigfun.userworld.com:20775  HTTP_USER_AGENT  => Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)  PATH  => /usr/bin:/bin:/usr/local/encap/ssh- 1.2.27.wsg.19991221/bin:/usr/X11/bin:/usr/andrew/bin:/usr/openwin/bin:/ usr/games:/usr/local/bin:/usr/bin/mh:~/bin  REMOTE_ADDR  => 209.16.196.244  REMOTE_PORT  => 4735  SCRIPT_FILENAME  => /home/webpages/userworld/htdocs/users/bigfun/useractivepreviewtmp208. php3  SERVER_ADMIN  => webmaster@bigfun.userworld.com  SERVER_NAME  => bigfun.userworld.com  SERVER_PORT  => 20775  SERVER_SIGNATURE  =>  Apache/1.3.6 Server at bigfun.userworld.com Port 20775   SERVER_SOFTWARE  => Apache/1.3.6 (Unix) PHP/4.0.4pl1 mod_perl/1.21  GATEWAY_INTERFACE  => CGI/1.1  SERVER_PROTOCOL  => HTTP/1.0  REQUEST_METHOD  => GET  QUERY_STRING  =>  REQUEST_URI  => /useractivepreviewtmp208.php3  SCRIPT_NAME  => /useractivepreviewtmp208.php3  PATH_TRANSLATED  => /home/webpages/userworld/htdocs/users/bigfun/useractivepreviewtmp208.   php3  PHP_SELF  => /useractivepreviewtmp208.php3  argv  => Array  argc  => 0 

Let's use just one element from this cornucopia in our code. We will try to be worldly and serve a different quiz to Spanish speakers . We use the browser's automatic language request to try to deliver a localized quiz.

Part of the header in every HTTP request is the line

HTTP
 Accept-Language: en-us 

It defines the preferred language of the visitor (in this case, the American dialect of English). We look for the prefix "sp" that will match any variation of Spanish:

HTTP
 Accept-Language: sp-ar 

Since we are not looking for the priority value of Spanish in the Accept-Language declaration, we will catch cases where Spanish is listed as acceptable but not the first choice.

In fact, we will have cases where the first choice is English and Spanish is the second choice:

HTTP
 Accept-Language: en-gb, en, fr;q=.8, sp;q=.1 

This user wants English, preferably British English. Failing that, she will accept French which she understands eight times better than her minimal Spanish. By our simple test, she too is a Spanish speaker.

PHP
 <?php header( "Content-Type: text/xml"); echo '<?xml version="1.0" encoding="UTF-8"?> '; echo '<Quiz>'; global  $HTTP_SERVER_VARS; if( strstr( $HTTP_SERVER_VARS["HTTP_ACCEPT_LANGUAGE"], "sp" )) {      echo '<Question>';      echo   'Einstein o Bohr: &#191;Qui&#233;n recibi&#243; el premio              Nobel?';      echo   '<Answer score="0">Einstein</Answer>';      echo   '<Answer score="0">Bohr</Answer>';      echo   '<Answer score="1">Ambos</Answer>';      echo   '<Answer score="0">Ninguno</Answer>';      echo '</Question>';      } else {      echo '<Question>';      echo  'Einstein or Bohr:  Who got the Nobel Prize for Physics?';      echo   '<Answer score="0">Einstein</Answer>';      echo   '<Answer score="0">Bohr</Answer>';      echo   '<Answer score="1">Both</Answer>';      echo   '<Answer score="0">Neither</Answer>';      echo   '</Question>';     } echo '      </Quiz>'; php?> 

Note that all the element and attribute names are never translated. Flash is not set up to detect a <Pregunta> , only a <Question> .

We also see the use of numeric entity references in Spanish. For example &#191; produces the symbol used in Spanish as the start tag for a question (Figure 10.2).

Figure 10.2. Output as Seen by Browser with Spanish Preference

graphics/10fig02.jpg



Flash and XML[c] A Developer[ap]s Guide
Flash and XML[c] A Developer[ap]s Guide
ISBN: 201729202
EAN: N/A
Year: 2005
Pages: 160

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net