Esempio n. 1
0
 /**
  * Parses the input code and returns the OPT XML tree.
  *
  * @param String $filename The file name (for debug purposes)
  * @param String &$code The code to parse
  * @return Opt_Xml_Root
  */
 public function parse($filename, &$code)
 {
     $debug = array(XMLReader::NONE => 'NONE', XMLReader::ELEMENT => 'ELEMENT', XMLReader::ATTRIBUTE => 'ATTRIBUTE', XMLReader::TEXT => 'TEXT', XMLReader::CDATA => 'CDATA', XMLReader::ENTITY_REF => 'ENTITY_REF', XMLReader::ENTITY => 'ENTITY', XMLReader::PI => 'PI', XMLReader::COMMENT => 'COMMENT', XMLReader::DOC => 'DOC', XMLReader::DOC_TYPE => 'DOC_TYPE', XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', XMLReader::NOTATION => 'NOTATION', XMLReader::WHITESPACE => 'WHITESPACE', XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', XMLReader::END_ELEMENT => 'END_ELEMENT', XMLReader::END_ENTITY => 'END_ENTITY', XMLReader::XML_DECLARATION => 'XML_DECLARATION');
     libxml_use_internal_errors(true);
     $reader = new XMLReader();
     $reader->xml($code);
     //	$reader->setParserProperty(XMLReader::LOADDTD, true);
     //	$reader->setParserProperty(XMLReader::VALIDATE, true);
     $reader->setParserProperty(XMLReader::SUBST_ENTITIES, true);
     $root = $current = new Opt_Xml_Root();
     $firstElementMatched = false;
     $depth = 0;
     // Thanks, Oh Great PHP for your excellent WARNINGS!!! >:(
     while (@$reader->read()) {
         if ($reader->depth < $depth) {
             $current = $current->getParent();
         } elseif ($reader->depth > $depth) {
             $current = $optNode;
         }
         //	Opl_Debug::write($debug[$reader->nodeType].': '.$reader->name.', '.$reader->value);
         switch ($reader->nodeType) {
             // XML elements
             case XMLReader::ELEMENT:
                 $optNode = new Opt_Xml_Element($reader->name);
                 // Parse element attributes, if you manage to get there
                 if ($reader->moveToFirstAttribute()) {
                     do {
                         // "xmlns" special namespace must be handler somehow differently.
                         if ($reader->prefix == 'xmlns') {
                             $ns = str_replace('xmlns:', '', $reader->name);
                             $root->addNamespace($ns, $reader->value);
                             // Let this attribute to appear, if it does not represent an OPT special
                             // namespace
                             if (!$this->_compiler->isNamespace($ns)) {
                                 $optAttribute = new Opt_Xml_Attribute($reader->name, $reader->value);
                                 $optNode->addAttribute($optAttribute);
                             }
                         } else {
                             $optAttribute = new Opt_Xml_Attribute($reader->name, $reader->value);
                             $optNode->addAttribute($optAttribute);
                         }
                     } while ($reader->moveToNextAttribute());
                     $reader->moveToElement();
                 }
                 // Set "rootNode" flag
                 if (!$firstElementMatched) {
                     $optNode->set('rootNode', true);
                     $firstElementMatched = true;
                 }
                 // Set "single" flag
                 if ($reader->isEmptyElement) {
                     $optNode->set('single', true);
                 }
                 $current->appendChild($optNode);
                 break;
             case XMLReader::TEXT:
                 $this->_treeTextCompile($current, $reader->value);
                 break;
             case XMLReader::COMMENT:
                 $optNode = new Opt_Xml_Comment($reader->value);
                 $current->appendChild($optNode);
                 break;
             case XMLReader::CDATA:
                 $cdata = new Opt_Xml_Cdata($reader->value);
                 $cdata->set('cdata', true);
                 if ($current instanceof Opt_Xml_Text) {
                     $current->appendChild($cdata);
                 } else {
                     $text = new Opt_Xml_Text();
                     $text->appendChild($cdata);
                     $current->appendChild($text);
                     $current = $text;
                 }
                 break;
                 /*		case XMLReader::SIGNIFICANT_WHITESPACE:
                 					$cdata = new Opt_Xml_Cdata($reader->value);
                 					$cdata->set('cdata', true);
                 
                 					if($current instanceof Opt_Xml_Text)
                 					{
                 						$current->appendChild($cdata);
                 					}
                 					else
                 					{
                 						$text = new Opt_Xml_Text();
                 						$text->appendChild($cdata);
                 						$current->appendChild($text);
                 						$current = $text;
                 					}
                 					break;
                 		 */
         }
         $depth = $reader->depth;
     }
     // Error checking
     $errors = libxml_get_errors();
     if (sizeof($errors) > 0) {
         libxml_clear_errors();
         foreach ($errors as $error) {
             echo $error->message . ' (' . $error->line . ')<br/>';
         }
     }
     return $root;
 }
Esempio n. 2
0
 /**
  * This helper method is the default instruction attribute handler in OPT.
  * It allows to parse the list of attributes using the specified rules.
  * The attribute configuration is passed as a second argument by reference,
  * and OPT returns the compiled attribute values in the same way.
  *
  * If the attribute specification contains "__UNKNOWN__" element, the node
  * may contain an undefined number of attributes. The undefined attributes
  * must match to the rules in "__UNKNOWN__" element and are returned by the
  * method as a separate array. For details, see the OPT user manual.
  *
  * @final
  * @param Opt_Xml_Element $subitem The scanned XML element.
  * @param Array &$config The reference to the attribute configuration
  * @return Array|Null The list of undefined attributes, if "__UNKNOWN__" is set.
  */
 protected final function _extractAttributes(Opt_Xml_Element $subitem, array &$config)
 {
     $required = array();
     $optional = array();
     $unknown = null;
     // Decide, what is what.
     foreach ($config as $name => &$data) {
         if (!isset($data[3])) {
             $data[3] = null;
         }
         if ($name == '__UNKNOWN__') {
             $unknown =& $data;
         } elseif ($data[0] == self::REQUIRED) {
             $required[$name] =& $data;
         } elseif ($data[0] == self::OPTIONAL) {
             $optional[$name] =& $data;
         }
     }
     $config = array();
     $return = array();
     $exprEngines = $this->_compiler->getExpressionEngines();
     // Parse required attributes
     $attrList = $subitem->getAttributes(false);
     foreach ($required as $name => &$data) {
         $ok = false;
         if (isset($attrList[$name])) {
             $aname = $name;
             $ok = true;
         } elseif (($data[1] == self::EXPRESSION || $data[1] == self::ASSIGN_EXPR) && $this->_tpl->backwardCompatibility == true) {
             // DEPRECATED: Legacy code for compatibility with OPT 2.0
             foreach ($exprEngines as $eeName => $eeValue) {
                 if (isset($attrList[$eeName . ':' . $name])) {
                     $aname = $eeName . ':' . $name;
                     $data[3] = $eeName;
                     $ok = true;
                     break;
                 }
             }
         }
         if (!$ok) {
             throw new Opt_AttributeNotDefined_Exception($name, $subitem->getXmlName());
         }
         $config[$name] = $this->_extractAttribute($subitem, $attrList[$aname], $data[1], $data[3]);
         unset($attrList[$aname]);
     }
     // Parse optional attributes
     foreach ($optional as $name => &$data) {
         $ok = false;
         if (isset($attrList[$name])) {
             $aname = $name;
             $ok = true;
         } elseif (($data[1] == self::EXPRESSION || $data[1] == self::ASSIGN_EXPR) && $this->_tpl->backwardCompatibility == true) {
             // DEPRECATED: Legacy code for compatibility with OPT 2.0
             foreach ($exprEngines as $eeName => $eeValue) {
                 if (isset($attrList[$eeName . ':' . $name])) {
                     $aname = $eeName . ':' . $name;
                     $data[3] = $eeName;
                     $ok = true;
                     break;
                 }
             }
         }
         if (!$ok) {
             // We can't use isset() because the default data might be "NULL"
             if (!array_key_exists(2, $data)) {
                 throw new Opt_APIMissingDefaultValue_Exception($name, $subitem->getXmlName());
             }
             $config[$name] = $data[2];
             continue;
         }
         $config[$name] = $this->_extractAttribute($subitem, $attrList[$aname], $data[1], $data[3]);
         unset($attrList[$aname]);
     }
     // The remaining tags must be processed using $unknown rule, however it
     // must be defined.
     if (!is_null($unknown)) {
         $type = $unknown[1];
         foreach ($attrList as $name => $attr) {
             try {
                 if (($type == self::EXPRESSION || $type == self::ASSIGN_EXPR) && $this->_tpl->backwardCompatibility == true) {
                     // DEPRECATED: Legacy code for compatibility with OPT 2.0
                     $exprType = $unknown[3];
                     foreach ($exprEngines as $eeName => $eeValue) {
                         if (isset($attrList[$eeName . ':' . $name])) {
                             $name = substr($name, strlen($eeName), strlen($name) - strlen($eeName));
                             $exprType = $eeName;
                             // Skip the tag, if this is a special OPT namespace.
                             if ($this->_compiler->isNamespace($exprType)) {
                                 throw new Exception();
                             }
                             break;
                         }
                     }
                 }
                 $return[$name] = $this->_extractAttribute($subitem, $attr, $type, $exprType);
             } catch (Exception $e) {
                 /* null */
             }
         }
     }
     return $return;
 }
Esempio n. 3
0
 /**
  * Looks for special OPT attributes in the element attribute list and
  * processes them. Returns the list of nodes that need to be postprocessed.
  *
  * @internal
  * @param Opt_Compiler_Class $compiler The compiler.
  * @param Boolean $specialNs Do we recognize special namespaces?
  */
 protected function _processXml(Opt_Compiler_Class $compiler, $specialNs = true)
 {
     if (!$this->hasAttributes()) {
         return array();
     }
     $attributes = $this->getAttributes();
     $this->_postprocess = array();
     $opt = Opl_Registry::get('opt');
     // Look for special OPT attributes
     foreach ($attributes as $attr) {
         if ($compiler->isNamespace($attr->getNamespace())) {
             $xml = $attr->getXmlName();
             if (($processor = $compiler->isOptAttribute($xml)) !== null) {
                 $processor->processAttribute($this, $attr);
                 if ($attr->get('postprocess')) {
                     $this->_postprocess[] = array($processor, $attr);
                 }
             }
             $this->removeAttribute($xml);
         } else {
             $compiler->compileAttribute($attr);
         }
     }
 }