Flash and XML[c] A Developer[ap]s Guide
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
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: ¿Quién recibió 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 ¿ 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
|