Exemple #1
0
 /**
  * Extracts attributes and content from an XML tag string.
  *
  * @param string $prefix The prefix of the tag definition.
  * @param string $name The name of the tag definition.
  * @param string $tagString The string, that contains the tag definition.
  *
  * @return string[] The attributes of the tag.
  * @throws ParserException In case of tag mismatch.
  *
  * @author Christian Achatz
  * @version
  * Version 0.1, 22.12.2006<br />
  * Version 0.2, 30.12.2006 (Bug-fix: tag-to-attribute delimiter is now a constant value)<br />
  * Version 0.3, 03.01.2007<br />
  * Version 0.4, 13.01.2007 (Improved error messages)<br />
  * Version 0.5, 16.11.2007 (Improved error message. Now affected tag string is displayed, too)<br />
  * Version 0.6, 03.11.2008 (Fixed the issue, that a TAB character is no valid token to attributes delimiter)<br />
  * Version 0.7, 04.11.2008 (Fixed issue, that a combination of TAB and SPACE characters leads to wrong attributes parsing)<br />
  * Version 0.8, 05.11.2008 (Removed the TAB support due to performance and fault tolerance problems)<br />
  * Version 0.9, 26.09.2012 (Introduced additional arguments for prefix and name to gain performance)<br />
  * Version 1.0, 23.12.2013 (ID#112: fixed parser issue with nested tags of the same tag name)<br />
  */
 public static function getTagAttributes($prefix, $name, $tagString)
 {
     // search for taglib to attributes string delimiter
     $tagAttributeDel = strpos($tagString, ' ');
     // search for the first appearance of the closing sign after the attribute string
     $posTagClosingSign = strpos($tagString, '>');
     // In case, the separator between tag and attribute is not found, or in case the tag
     // end position is located between the tag and the attribute, the end sign (">") is used
     // as separator. This allows tags without attributes.
     if ($tagAttributeDel === false || $tagAttributeDel > $posTagClosingSign) {
         $tagAttributeDel = strpos($tagString, '>');
     }
     // extract the rest of the tag string.
     $attributesString = substr($tagString, $tagAttributeDel + 1, $posTagClosingSign - $tagAttributeDel);
     // ID#253: In case we are using an extended templating expression within a tag attribute
     // (e.g. "model[0]->getFoo()") the ending ">" is contained within the attribute and thus the first
     // substr() produces wrong results. For this reason, search for the last ">" with an even number of
     // quotes in the string to fix this.
     $parserLoops = 0;
     while (substr_count($attributesString, '"') % 2 !== 0) {
         $parserLoops++;
         // limit parse loop count to avoid endless searching
         if ($parserLoops > self::$maxParserLoops) {
             throw new ParserException('[XmlParser::getTagAttributes()] Error while parsing: "' . $tagString . '". Maximum number of loops ("' . self::$maxParserLoops . '") exceeded!', E_USER_ERROR);
         }
         $posTagClosingSign = strpos($tagString, '>', $posTagClosingSign + 1);
         $attributesString = substr($tagString, $tagAttributeDel + 1, $posTagClosingSign - $tagAttributeDel);
     }
     // parse the tag's attributes
     $tagAttributes = XmlParser::getAttributesFromString($attributesString);
     // Check, whether the tag is self-closing. If not, read the content.
     if (substr($tagString, $posTagClosingSign - 1, 1) == '/') {
         $content = '';
     } else {
         // search for the outer-most explicit closing tag to support nested tag hierarchies
         $tagEndPos = strrpos($tagString, '</' . $prefix . ':' . $name . '>');
         if ($tagEndPos === false) {
             throw new ParserException('[XmlParser::getTagAttributes()] No closing tag found for ' . 'tag "<' . $prefix . ':' . $name . ' />"! Tag string: "' . $tagString . '".', E_USER_ERROR);
         }
         // read the content of the tag
         $content = substr($tagString, $posTagClosingSign + 1, $tagEndPos - $posTagClosingSign - 1);
     }
     return ['attributes' => $tagAttributes, 'content' => $content];
 }