示例#1
0
function readCommon($xml)
{
    $depth = $xml->depth;
    $text = "";
    while ($xml->levelRead($depth)) {
        if ($xml->nodeType == XMLReader::ELEMENT) {
            $text .= "<property name=\"{$xml->name}\" value=\"" . xmlspecialchars($xml->readString()) . "\"/>\n";
        }
    }
    return $text;
}
示例#2
0
 /**
 	Select the given value.
 
 	@param $sValue The value to select.
 */
 protected function selectItem($sValue)
 {
     $sEscapedValue = xmlspecialchars($sValue);
     $aOption = $this->oXML->options->xpath('.//item[(not(@value) and @label="' . $sEscapedValue . '" or @value="' . $sEscapedValue . '") and not(@disabled)]');
     $iSize = count($aOption);
     $iSize > 1 and burn('BadXMLException', _WT('The value was found more than once in the options.'));
     if ($iSize == 1) {
         $aOption[0]['selected'] = 'selected';
     }
 }
示例#3
0
<?php

$this->isEqual('Time to say &apos;night.', xmlspecialchars("Time to say 'night."), _WT("Encoding of ' failed."));
$this->isEqual('&quot;&gt;_&gt;&quot; &amp; &quot;&lt;_&lt;&quot;', xmlspecialchars('">_>" & "<_<"'), _WT('Encoding of ">_>" & "<_<" failed.'));
$this->isEqual('東方妖々夢', xmlspecialchars('東方妖々夢'), _WT('xmlspecialchars should not encode unicode characters.'));
示例#4
0
 public function buildQTI($data = null)
 {
     if (!is_null($data)) {
         $this->data = $data;
     }
     if (empty($this->data)) {
         return false;
     }
     // container element and other metadata
     $ai = $this->initialXML();
     // response declarations
     for ($g = 0; array_key_exists("gap_{$g}_response_0", $this->data); $g++) {
         $rd = $ai->addChild("responseDeclaration");
         $rd->addAttribute("identifier", "RESPONSE_gap_{$g}");
         $rd->addAttribute("cardinality", "single");
         $rd->addAttribute("baseType", "string");
         $m = $rd->addChild("mapping");
         $m->addAttribute("defaultValue", "0");
         for ($r = 0; array_key_exists("gap_{$g}_response_{$r}", $this->data); $r++) {
             $me = $m->addChild("mapEntry");
             $me->addAttribute("mapKey", $this->data["gap_{$g}_response_{$r}"]);
             $me->addAttribute("mappedValue", $this->data["gap_{$g}_response_{$r}_score"]);
         }
     }
     // outcome declaration
     $od = $ai->addChild("outcomeDeclaration");
     $od->addAttribute("identifier", "SCORE");
     $od->addAttribute("cardinality", "single");
     $od->addAttribute("baseType", "float");
     $od->addChild("defaultValue");
     $od->defaultValue->addChild("value", "0");
     // item body
     $ib = $ai->addChild("itemBody");
     // get stimulus and add to the XML tree
     if (isset($this->data["stimulus"]) && !empty($this->data["stimulus"])) {
         $this->data["stimulus"] = wrapindiv($this->data["stimulus"]);
         // parse it as XML
         $stimulus = stringtoxml($this->data["stimulus"], "stimulus");
         if (is_array($stimulus)) {
             // errors
             $this->errors[] = "Stimulus is not valid XML. It must not only be valid XML but valid QTI, which accepts a subset of XHTML. Details on specific issues follow:";
             $this->errors = array_merge($this->errors, $stimulus);
         } else {
             simplexml_append($ib, $stimulus);
         }
     }
     // div with class eqiat-te
     $d = $ib->addChild("div");
     $d->addAttribute("class", "eqiat-te");
     // body text
     $bt = $d->addChild("div");
     $bt->addAttribute("class", "textentrytextbody");
     $text = xmlspecialchars($this->data["textbody"]);
     $text = preg_replace('%\\n\\n+%', "</p><p>", $text);
     $text = preg_replace('%\\n%', "<br/>", $text);
     $text = "<p>" . $text . "</p>";
     $g = 0;
     $start = 0;
     while (($start = strpos($text, "[", $start)) !== false) {
         $start = strpos($text, "[");
         $end = strpos($text, "]", $start);
         // base expected length on the longest answer plus 10%
         $el = 0;
         for ($r = 0; array_key_exists("gap_{$g}_response_{$r}", $this->data); $r++) {
             $el = max($el, strlen($this->data["gap_{$g}_response_{$r}"]));
         }
         $el = ceil($el * 1.1);
         $text = substr($text, 0, $start) . '<textEntryInteraction responseIdentifier="RESPONSE_gap_' . $g++ . '" expectedLength="' . $el . '"/>' . substr($text, $end + 1);
     }
     // parse it as XML
     libxml_use_internal_errors(true);
     $textxml = simplexml_load_string($text);
     if ($textxml === false) {
         $this->errors[] = "Text body did not convert to valid XML";
         foreach (libxml_get_errors() as $error) {
             $this->errors[] = "Text body line " . $error->line . ", column " . $error->column . ": " . $error->message;
         }
         libxml_clear_errors();
     } else {
         simplexml_append($bt, $textxml);
     }
     libxml_use_internal_errors(false);
     // response processing
     $rp = $ai->addChild("responseProcessing");
     // set score = 0
     $sov = $rp->addChild("setOutcomeValue");
     $sov->addAttribute("identifier", "SCORE");
     $sov->addChild("baseValue", "0.0")->addAttribute("baseType", "float");
     for ($g = 0; array_key_exists("gap_{$g}_response_0", $this->data); $g++) {
         $rc = $rp->addChild("responseCondition");
         // if
         $ri = $rc->addChild("responseIf");
         // not null
         $ri->addChild("not")->addChild("isNull")->addChild("variable")->addAttribute("identifier", "RESPONSE_gap_{$g}");
         // increment score
         $sov = $ri->addChild("setOutcomeValue");
         $sov->addAttribute("identifier", "SCORE");
         $s = $sov->addChild("sum");
         $s->addChild("variable")->addAttribute("identifier", "SCORE");
         $s->addChild("mapResponse")->addAttribute("identifier", "RESPONSE_gap_{$g}");
     }
     if (!empty($this->errors)) {
         return false;
     }
     // validate the QTI
     validateQTI($ai, $this->errors, $this->warnings, $this->messages);
     if (!empty($this->errors)) {
         return false;
     }
     $this->qti = $ai;
     return $this->qti;
 }
示例#5
0
 /**
 	Output the form to string.
 
 	@return string The resulting XHTML form.
 */
 public function toString()
 {
     $oDoc = new DOMDocument();
     $oXSL = new XSLTProcessor();
     $oDoc->loadXML($this->buildXSLStylesheet());
     $oXSL->importStyleSheet($oDoc);
     // time consuming
     $oWidgetsNode = $this->xpathOne('//widgets');
     $oWidgetsNode = dom_import_simplexml($oWidgetsNode);
     // If some fields are required we put a label on top to inform the user
     if (count($this->oXML->xpath('//widget[@required]')) > 0) {
         $oOwnerDoc = $oWidgetsNode->ownerDocument;
         $oNode = $oOwnerDoc->createElement('ol');
         $oNode->setAttribute('class', 'notice required');
         $oWidgetsNode->insertBefore($oNode, $oWidgetsNode->firstChild);
         $o = $oOwnerDoc->createElement('li');
         $oNode->appendChild($o);
         $aNotice = explode('*', _WT('The fields marked with * are required.'));
         $o->appendChild($oOwnerDoc->createTextNode($aNotice[0]));
         $o->appendChild($oOwnerDoc->createElement('em', '*'));
         $o->appendChild($oOwnerDoc->createTextNode($aNotice[1]));
     }
     // If we have any error we put a friendly message on top
     // $oErrorOl created here is also used to display global error messages
     if (!empty($this->aErrors)) {
         $oErrorOl = $oWidgetsNode->ownerDocument->createElement('ol');
         $oErrorOl->setAttribute('class', 'error');
         $oWidgetsNode->insertBefore($oErrorOl, $oWidgetsNode->firstChild);
         $oErrorOl = simplexml_import_dom($oErrorOl);
         $o = $oErrorOl->addChild('li');
         $o->addChild('strong', _WT('One or more errors have been detected.'));
     }
     // Fill in the values and errors if any
     $aKeys = array_keys(array_merge($this->aData, $this->aErrors));
     foreach ($aKeys as $sName) {
         // For global errors (namely errors with an empty string as widget name), we create
         // an ordered list at the beginning of the form and put the errors inside it.
         if (empty($sName)) {
             if (is_array($this->aErrors[$sName])) {
                 foreach ($this->aErrors[$sName] as $sMsg) {
                     $oErrorOl->addChild('li', $sMsg);
                 }
             } else {
                 $oErrorOl->addChild('li', $this->aErrors[$sName]);
             }
             continue;
         }
         // If it isn't a global error we fill values and errors normally
         ctype_print($sName) or burn('InvalidArgumentException', _WT('The widget name must be printable.'));
         $a = $this->oXML->xpath('//widget[name="' . xmlspecialchars($sName) . '"]');
         if (!empty($a)) {
             $oWidget = $a[0];
             if (isset($this->aData[$sName])) {
                 if (empty($oWidget->options)) {
                     $oWidget->value = $this->aData[$sName];
                 } else {
                     $oOptionHelper = $this->helper('weeFormOptionsHelper', $sName);
                     if (empty($oWidget->options['multiple'])) {
                         if ($oOptionHelper->isInOptions($this->aData[$sName])) {
                             $oOptionHelper->select($this->aData[$sName]);
                         }
                     } else {
                         foreach ($this->aData[$sName] as $mValue) {
                             if ($oOptionHelper->isInOptions($mValue)) {
                                 $oOptionHelper->select($mValue);
                             }
                         }
                     }
                 }
             }
             if (!empty($this->aErrors[$sName])) {
                 if (!empty($oWidget->errors)) {
                     $oNode = dom_import_simplexml($oWidget->errors);
                     $oNode->parentNode->removeChild($oNode);
                 }
                 $oWidget->addChild('errors');
                 if (is_array($this->aErrors[$sName])) {
                     foreach ($this->aErrors[$sName] as $sMsg) {
                         $oWidget->errors->addChild('error', $sMsg);
                     }
                 } else {
                     $oWidget->errors->addChild('error', $this->aErrors[$sName]);
                 }
             }
         }
     }
     return $oXSL->transformToXML(dom_import_simplexml($this->oXML)->ownerDocument);
 }
    creationtool="OmegaT"
    creationtoolversion="1.7.3_1"
    segtype="sentence"
    o-tmf="OmegaT TMX"
    adminlang="EN-US"
    srclang="EN"
    datatype="plaintext"
  >
  </header>
  <body>
EOT;
fwrite($f_out, $str);
reset($src_list);
while (list($k, $v) = each($src_list)) {
    $k = xmlspecialchars($k);
    $v = xmlspecialchars($v);
    $str = <<<EOT
    <tu>
      <tuv lang="EN">
        <seg>{$k}</seg>
      </tuv>
      <tuv lang="{$dest_lang}">
        <seg>{$v}</seg>
      </tuv>
    </tu>
EOT;
    fwrite($f_out, $str);
}
$str = "</body>\n</tmx>";
fwrite($f_out, $str);
fclose($f_out);
示例#7
0
function makeTag($name, $attributes = null, $textContent = null, $close = true, $encodeContent = true)
{
    $tag = "<{$name}";
    if (is_array($attributes)) {
        foreach ($attributes as $attr => $value) {
            $tag .= ' ' . xmlspecialchars($attr) . '="' . xmlspecialchars($value) . '"';
        }
    }
    if ($close && !$textContent) {
        $tag .= '/>';
    } else {
        $tag .= '>';
    }
    if ($textContent) {
        if ($encodeContent) {
            $tag .= xmlspecialchars($textContent);
        } else {
            $tag .= $textContent;
        }
        $tag .= "</{$name}>";
    }
    output($tag . "\n");
}
function renderVastOutput($aOut, $pluginType, $vastAdDescription)
{
    $adName = $aOut['name'];
    $player = "";
    $player .= "    <Ad id=\"{player_allocated_ad_id}\" >";
    $player .= "        <InLine>";
    $player .= "            <AdSystem>OpenX</AdSystem>\n";
    $player .= "                <AdTitle><![CDATA[{$adName}]]></AdTitle>\n";
    $player .= "                    <Description><![CDATA[{$vastAdDescription}]]></Description>\n";
    $player .= "                    <Impression>\n";
    $player .= "                        <URL id=\"primaryAdServer\"><![CDATA[{$aOut['impressionUrl']}]]></URL>\n";
    if (!empty($aOut['thirdPartyImpressionUrl'])) {
        $player .= "                        <URL id=\"secondaryAdServer\"><![CDATA[{$aOut['thirdPartyImpressionUrl']}]]></URL>\n";
    }
    $player .= "                    </Impression>\n";
    if (isset($aOut['companionMarkup'])) {
        if (!empty($aOut['companionClickUrl'])) {
            $CompanionClickThrough = "                    <CompanionClickThrough>\n";
            $CompanionClickThrough .= "                        <URL><![CDATA[{$aOut['companionClickUrl']}]]></URL>\n";
            $CompanionClickThrough .= "                    </CompanionClickThrough>\n";
        }
        //debugdump( '$companionOutput', $companionOutput );
        $player .= "             <CompanionAds>\n";
        $player .= "                <Companion id=\"companion\" width=\"{$aOut['companionWidth']}\" height=\"{$aOut['companionHeight']}\" resourceType=\"HTML\">\n";
        $player .= "                    <Code><![CDATA[{$aOut['companionMarkup']}]]></Code>\n";
        $player .= "\t\t\t\t\t{$CompanionClickThrough}";
        $player .= "                </Companion>\n";
        $player .= "            </CompanionAds>\n";
    }
    if ($pluginType == 'vastOverlay') {
        $code = $resourceType = $creativeType = $elementName = '';
        switch ($aOut['overlayFormat']) {
            case VAST_OVERLAY_FORMAT_HTML:
                $code = "<![CDATA[" . $aOut['overlayMarkupTemplate'] . "]]>";
                $resourceType = 'HTML';
                $elementName = 'Code';
                break;
            case VAST_OVERLAY_FORMAT_IMAGE:
                $creativeType = strtoupper($aOut['overlayContentType']);
                // BC when the overlay_creative_type field is not set in the DB
                if (empty($creativeType)) {
                    $creativeType = strtoupper(substr($aOut['overlayFilename'], -3));
                    // case of .jpeg files OXPL-493
                    if ($creativeType == 'PEG') {
                        $creativeType = 'JPEG';
                    }
                }
                if ($creativeType == 'JPEG') {
                    $creativeType = 'JPG';
                }
                $creativeType = 'image/' . $creativeType;
                $code = getImageUrlFromFilename($aOut['overlayFilename']);
                $resourceType = 'static';
                $elementName = 'URL';
                break;
            case VAST_OVERLAY_FORMAT_SWF:
                $creativeType = 'application/x-shockwave-flash';
                $code = getImageUrlFromFilename($aOut['overlayFilename']);
                $resourceType = 'static';
                $elementName = 'URL';
                break;
            case VAST_OVERLAY_FORMAT_TEXT:
                $resourceType = 'TEXT';
                $code = "<![CDATA[\n                \t<Title>" . xmlspecialchars($aOut['overlayTextTitle']) . "</Title>\n               \t\t<Description>" . xmlspecialchars($aOut['overlayTextDescription']) . "</Description>\n               \t\t<CallToAction>" . xmlspecialchars($aOut['overlayTextCall']) . "</CallToAction>\n               \t\t]]>\n               ";
                $elementName = 'Code';
                break;
        }
        if (!empty($aOut['clickUrl'])) {
            $nonLinearClickThrough = "<NonLinearClickThrough>\n                    <URL><![CDATA[{$aOut['clickUrl']}]]></URL>\n                </NonLinearClickThrough>\n";
        }
        $creativeTypeAttribute = '';
        if (!empty($creativeType)) {
            $creativeType = strtolower($creativeType);
            $creativeTypeAttribute = 'creativeType="' . $creativeType . '"';
        }
        $player .= "             <NonLinearAds>\n";
        $player .= "                <NonLinear id=\"overlay\" width=\"{$aOut['overlayWidth']}\" height=\"{$aOut['overlayHeight']}\" resourceType=\"{$resourceType}\" {$creativeTypeAttribute}>\n";
        $player .= "                    <{$elementName}>\n        \t\t\t\t\t\t\t\t\t{$code}\n        \t\t\t\t\t\t\t\t</{$elementName}>\n";
        $player .= "                    {$nonLinearClickThrough}";
        $player .= "                </NonLinear>\n";
        $player .= "            </NonLinearAds>\n";
    }
    if (isset($aOut['fullPathToVideo'])) {
        $player .= getVastVideoAdOutput($aOut);
    }
    $player .= "        </InLine>\n";
    $player .= "    </Ad>\n";
    return $player;
}
function begin_document($path)
{
    global $PHP_SELF, $base_url, $id_pool, $assessments, $basepath, $collection, $document, $phpext;
    //   print "$basepath";
    $id = get_full_path($basepath, $path);
    if ($document[$id]) {
        $a =& $document[$id];
        if ($a[1]) {
            print "<span style=\"padding: 2px; border: 1px dashed blue\" title=\"in pool\">";
        } else {
            print "<span>";
        }
        switch ($a[0]) {
            case "0":
                print "<img style=\"vertical-align: center;\" src=\"{$base_url}/img/mode_highlight\" title=\"highlighting mode\" alt=\"[highlighting]\"/>";
                break;
            case "1":
                print "<img style=\"vertical-align: center;\" src=\"{$base_url}/img/nok\" title=\"assessing mode (not validated)\" alt=\"[assessing]\"/>";
                break;
            case "2":
                print "<img style=\"vertical-align: center;\"  src=\"{$base_url}/img/ok\" title=\"assessing mode (validated)\" alt=\"[validated]\"/>";
                break;
        }
        print "</span> ";
    }
    print "<a id='" . xmlspecialchars($id) . "'" . ($a[1] ? " name='toAssess'" : "") . " href=\"{$base_url}/article{$phpext}?collection={$collection}&amp;id_pool={$id_pool}&amp;file={$id}\">";
}
示例#10
0
 /**
 	Create the form from a set metadata. Called by the class' constructor.
 
 	@param $oSet The set to build the form for.
 */
 protected function loadFromSet($oSet)
 {
     $aMeta = $oSet->getMeta();
     $aRefSets = $this->loadRefSets($oSet);
     $this->oXML = simplexml_load_string('<form><method>' . xmlspecialchars(array_value($this->aOptions, 'method', 'post')) . '</method><widgets><widget type="fieldset"/></widgets></form>');
     foreach ($aMeta['colsobj'] as $oCol) {
         $sColumn = $oCol->name();
         // Ignore given columns
         if (in_array($sColumn, $this->aOptions['ignorecolumns'])) {
             continue;
         }
         if (!empty($aRefSets[$sColumn])) {
             $this->addWidget('choice', $oCol);
             $sLabelColumn = $aRefSets[$sColumn]['key'];
             foreach ($aRefSets[$sColumn]['meta']['columns'] as $sRefColumn) {
                 if (strpos($sRefColumn, 'label') !== false) {
                     $sLabelColumn = $sRefColumn;
                     break;
                 }
             }
             $oHelper = $this->helper('weeFormOptionsHelper', $sColumn);
             $oHelper->addOption(array('label' => 'NULL', 'value' => ''));
             foreach ($aRefSets[$sColumn]['set']->fetchAll() as $aRow) {
                 $oHelper->addOption(array('label' => $aRow[$sLabelColumn], 'value' => $aRow[$aRefSets[$sColumn]['key']]));
             }
         } else {
             $sWidget = 'textbox';
             if (in_array($sColumn, $aMeta['primary']) && empty($this->aOptions['show-pkey'])) {
                 if ($this->aOptions['action'] != 'update') {
                     continue;
                 }
                 $sWidget = 'hidden';
             } elseif (strpos($sColumn, '_is_')) {
                 $sWidget = 'checkbox';
             } elseif (strpos($sColumn, 'password')) {
                 $sWidget = 'password';
             }
             $this->addWidget($sWidget, $oCol);
         }
     }
     $oFieldset = $this->oXML->widgets->widget->addChild('widget');
     $oFieldset->addAttribute('type', 'fieldset');
     $oFieldset->addChild('class', 'buttonsfieldset');
     if ($this->aOptions['action'] == 'update') {
         $oButton = $oFieldset->addChild('widget');
         $oButton->addAttribute('type', 'resetbutton');
     }
     $oButton = $oFieldset->addChild('widget');
     $oButton->addAttribute('type', 'submitbutton');
 }
示例#11
0
 /**
 	Encode a given value.
 
 	@param	$mValue	The value to encode.
 	@return	string	The encoded value.
 */
 public function encode($mValue)
 {
     return xmlspecialchars($mValue);
 }
示例#12
0
 /**
 	Select elements in the XML document.
 
 	@param	$sSelect	The selector.
 	@param	$oDocument	The XML document.
 	@param	$oXPath		The XPATH object for this document.
 	@return	DOMNodeList	The selected elements.
 */
 protected function select($sSelect, DOMDocument $oDocument, DOMXPath $oXPath)
 {
     if ($sSelect[0] == '#') {
         return $oXPath->query('//*[@id="' . xmlspecialchars(substr($sSelect, 1)) . '"]');
     }
     if (strpos($sSelect, '/') !== false) {
         return $oXPath->query($sSelect);
     }
     return $oDocument->getElementsByTagName($sSelect);
 }
示例#13
0
 public static function xml_pretty_printer($xml, $html_output = FALSE)
 {
     $xml_obj = new SimpleXMLElement($xml);
     $xml_lines = explode("\n", str_replace("><", ">\n<", $xml_obj->asXML()));
     $indent_level = 0;
     $new_xml_lines = array();
     foreach ($xml_lines as $xml_line) {
         if (preg_match('#^(<[a-z0-9_:-]+((\\s+[a-z0-9_:-]+="[^"]+")*)?>.*<\\s*/\\s*[^>]+>)|(<[a-z0-9_:-]+((\\s+[a-z0-9_:-]+="[^"]+")*)?\\s*/\\s*>)#i', ltrim($xml_line))) {
             $new_line = str_pad('', $indent_level * 4) . ltrim($xml_line);
             $new_xml_lines[] = $new_line;
             #	   $new_xml_lines[] = "Didn't increment 1.";
         } elseif (preg_match('#^<[a-z0-9_:-]+((\\s+[a-z0-9_:-]+="[^"]+")*)?>#i', ltrim($xml_line))) {
             $new_line = str_pad('', $indent_level * 4) . ltrim($xml_line);
             $indent_level++;
             $new_xml_lines[] = $new_line;
             #	   $new_xml_lines[] = "Increment.";
         } elseif (preg_match('#<\\s*/\\s*[^>/]+>#i', $xml_line)) {
             $indent_level--;
             if (trim($new_xml_lines[sizeof($new_xml_lines) - 1]) == trim(str_replace("/", "", $xml_line))) {
                 $new_xml_lines[sizeof($new_xml_lines) - 1] .= $xml_line;
                 #	      $new_xml_lines[] = "Decrement 1.";
             } else {
                 $new_line = str_pad('', $indent_level * 4) . $xml_line;
                 $new_xml_lines[] = $new_line;
                 #	      $new_xml_lines[] = "Decrement 2.";
             }
         } else {
             $new_line = str_pad('', $indent_level * 4) . $xml_line;
             $new_xml_lines[] = $new_line;
             #	   $new_xml_lines[] = "Didn't increment 2.";
         }
     }
     $xml = join("\n", $new_xml_lines);
     return $html_output ? '<pre>' . xmlspecialchars($xml) . '</pre>' : $xml;
 }
示例#14
0
/**
 * Input: the data (in string form) from the polling locations file.
 * Returns the feed contents for polling locations
 */
function addLocations($datastr)
{
    addLogMessage("Start Locations");
    $locArray = parseCSV($datastr);
    $str = "";
    $savedID = -1;
    $savedName = "";
    foreach ($locArray as $loc) {
        $curID = $loc[0];
        $curName = $loc[2];
        if (strlen($curID) > 0 && strcmp($curID, "ID") != 0 && strcmp(trim($curName), "MAIL BALLOT PRECINCT") != 0) {
            if ($savedID != $curID) {
                $str .= "<polling_location id=\"" . $curID . "\">";
                $str .= "<address>";
                $str .= " <location_name>" . xmlspecialchars($loc[2]) . "</location_name>";
                $str .= " <line1>" . xmlspecialchars($loc[3]) . "</line1>";
                $str .= " <city>" . xmlspecialchars($loc[4]) . "</city>";
                $str .= " <state>NM</state>";
                $str .= " <zip>" . xmlspecialchars($loc[5]) . "</zip>";
                $str .= "</address>";
                $str .= "<directions>" . xmlspecialchars(trim($loc[6])) . "</directions>";
                $str .= "</polling_location>\n";
            }
        }
        $savedID = $curID;
        $savedName = $curName;
    }
    addLogMessage("End Locations");
    return $str;
}
 public function buildQTI($data = null)
 {
     if (!is_null($data)) {
         $this->data = $data;
     }
     if (empty($this->data)) {
         return false;
     }
     // container element and other metadata
     $ai = $this->initialXML();
     // response declarations
     for ($q = 0; array_key_exists("question_{$q}_prompt", $this->data); $q++) {
         $rd = $ai->addChild("responseDeclaration");
         $rd->addAttribute("identifier", "RESPONSE_question_{$q}");
         $rd->addAttribute("cardinality", "multiple");
         $rd->addAttribute("baseType", "identifier");
         // build array of correct responses
         $correct = array();
         for ($o = 0; array_key_exists("option_{$o}_optiontext", $this->data); $o++) {
             if (isset($this->data["question_{$q}_option_{$o}_correct"])) {
                 $correct[] = $o;
             }
         }
         // add correctResponse node only if any options are correct
         if (!empty($correct)) {
             $rd->addChild("correctResponse");
             foreach ($correct as $o) {
                 $rd->correctResponse->addChild("value", "question_{$q}_option_{$o}");
             }
         }
     }
     // outcome declaration
     $od = $ai->addChild("outcomeDeclaration");
     $od->addAttribute("identifier", "SCORE");
     $od->addAttribute("cardinality", "single");
     $od->addAttribute("baseType", "integer");
     $od->addChild("defaultValue");
     $od->defaultValue->addChild("value", "0");
     // item body
     $ib = $ai->addChild("itemBody");
     // get stimulus and add to the XML tree
     if (isset($this->data["stimulus"]) && !empty($this->data["stimulus"])) {
         $this->data["stimulus"] = wrapindiv($this->data["stimulus"]);
         // parse it as XML
         $stimulus = stringtoxml($this->data["stimulus"], "stimulus");
         if (is_array($stimulus)) {
             // errors
             $this->errors[] = "Stimulus is not valid XML. It must not only be valid XML but valid QTI, which accepts a subset of XHTML. Details on specific issues follow:";
             $this->errors = array_merge($this->errors, $stimulus);
         } else {
             simplexml_append($ib, $stimulus);
         }
     }
     // div with class eqiat-emi
     $d = $ib->addChild("div");
     $d->addAttribute("class", "eqiat-emi");
     // list the options
     $options = "";
     for ($o = 0; array_key_exists("option_{$o}_optiontext", $this->data); $o++) {
         $options .= "<li>" . xmlspecialchars($this->data["option_{$o}_optiontext"]) . "</li>";
     }
     simplexml_append($d, simplexml_load_string('<ol class="emioptions">' . $options . '</ol>'));
     // questions
     for ($q = 0; array_key_exists("question_{$q}_prompt", $this->data); $q++) {
         $ci = $d->addChild("choiceInteraction");
         $ci->addAttribute("maxChoices", "0");
         $ci->addAttribute("minChoices", "0");
         $ci->addAttribute("shuffle", "false");
         $ci->addAttribute("responseIdentifier", "RESPONSE_question_{$q}");
         $ci->addChild("prompt", $this->data["question_{$q}_prompt"]);
         for ($o = 0; array_key_exists("option_{$o}_optiontext", $this->data); $o++) {
             $sc = $ci->addChild("simpleChoice", chr(ord("A") + $o));
             $sc->addAttribute("identifier", "question_{$q}_option_{$o}");
         }
     }
     // response processing
     $rp = $ai->addChild("responseProcessing");
     // set score = 0
     $sov = $rp->addChild("setOutcomeValue");
     $sov->addAttribute("identifier", "SCORE");
     $sov->addChild("baseValue", "0")->addAttribute("baseType", "integer");
     for ($q = 0; array_key_exists("question_{$q}_prompt", $this->data); $q++) {
         $rc = $rp->addChild("responseCondition");
         // if
         $ri = $rc->addChild("responseIf");
         // build array of correct responses
         $correct = array();
         for ($o = 0; array_key_exists("option_{$o}_optiontext", $this->data); $o++) {
             if (isset($this->data["question_{$q}_option_{$o}_correct"])) {
                 $correct[] = $o;
             }
         }
         // criteria for a correct answer
         if (empty($correct)) {
             // multiple response in which the correct response is to tick no
             // boxes -- check number of responses is equal to zero
             $e = $ri->addChild("equal");
             $e->addAttribute("toleranceMode", "exact");
             $e->addChild("containerSize")->addChild("variable")->addAttribute("identifier", "RESPONSE_question_{$q}");
             $e->addChild("baseValue", "0")->addAttribute("baseType", "integer");
         } else {
             // otherwise, we match responses to the correctResponse above
             $m = $ri->addChild("match");
             $m->addChild("variable")->addAttribute("identifier", "RESPONSE_question_{$q}");
             $m->addChild("correct")->addAttribute("identifier", "RESPONSE_question_{$q}");
         }
         // increment score
         $sov = $ri->addChild("setOutcomeValue");
         $sov->addAttribute("identifier", "SCORE");
         $s = $sov->addChild("sum");
         $s->addChild("variable")->addAttribute("identifier", "SCORE");
         $s->addChild("baseValue", "1")->addAttribute("baseType", "integer");
     }
     if (!empty($this->errors)) {
         return false;
     }
     // validate the QTI
     validateQTI($ai, $this->errors, $this->warnings, $this->messages);
     if (!empty($this->errors)) {
         return false;
     }
     $this->qti = $ai;
     return $this->qti;
 }