eZXMLInputParser::parseTag PHP Method

parseTag() public method

The main recursive function for pass 1
public parseTag ( &$data, &$pos, &$parent )
    function parseTag(&$data, &$pos, &$parent)
    {
        // Find tag, determine it's type, name and attributes.
        $initialPos = $pos;
        if ($pos >= strlen($data)) {
            return true;
        }
        $tagBeginPos = strpos($data, '<', $pos);
        if ($this->ParseLineBreaks) {
            // Regard line break as a start tag position
            $lineBreakPos = strpos($data, "\n", $pos);
            if ($lineBreakPos !== false) {
                $tagBeginPos = $tagBeginPos === false ? $lineBreakPos : min($tagBeginPos, $lineBreakPos);
            }
        }
        $tagName = '';
        $attributes = null;
        // If it doesn't begin with '<' then its a text node.
        if ($tagBeginPos != $pos || $tagBeginPos === false) {
            $pos = $initialPos;
            $tagName = $newTagName = '#text';
            $noChildren = true;
            if (!$tagBeginPos) {
                $tagBeginPos = strlen($data);
            }
            $textContent = substr($data, $pos, $tagBeginPos - $pos);
            $textContent = $this->washText($textContent);
            $pos = $tagBeginPos;
            if ($textContent === '') {
                return false;
            }
        } elseif ($data[$tagBeginPos] == '<' && $tagBeginPos + 1 < strlen($data) && $data[$tagBeginPos + 1] == '/') {
            $tagEndPos = strpos($data, '>', $tagBeginPos + 1);
            if ($tagEndPos === false) {
                $pos = $tagBeginPos + 1;
                $this->handleError(self::ERROR_SYNTAX, ezpI18n::tr('kernel/classes/datatypes/ezxmltext', 'Wrong closing tag'));
                return false;
            }
            $pos = $tagEndPos + 1;
            $closedTagName = strtolower(trim(substr($data, $tagBeginPos + 2, $tagEndPos - $tagBeginPos - 2)));
            // Find matching tag in ParentStack array
            $firstLoop = true;
            for ($i = count($this->ParentStack) - 1; $i >= 0; $i--) {
                $parentNames = $this->ParentStack[$i];
                if ($parentNames[0] == $closedTagName) {
                    array_pop($this->ParentStack);
                    if (!$firstLoop) {
                        $pos = $tagBeginPos;
                        return true;
                    } elseif ($parentNames[1] !== '') {
                        return true;
                    } else {
                        return false;
                    }
                }
                $firstLoop = false;
            }
            $this->handleError(self::ERROR_SYNTAX, ezpI18n::tr('kernel/classes/datatypes/ezxmltext', 'Wrong closing tag : &lt;/%1&gt;.', false, array($closedTagName)));
            return false;
        } elseif ($this->ParseLineBreaks && $data[$tagBeginPos] == "\n") {
            $newTagName = 'br';
            $noChildren = true;
            $pos = $tagBeginPos + 1;
        } else {
            $tagEndPos = $this->findEndOpeningTagPosition($data, $tagBeginPos);
            if ($tagEndPos === false) {
                $pos = $tagBeginPos + 1;
                $this->handleError(self::ERROR_SYNTAX, ezpI18n::tr('kernel/classes/datatypes/ezxmltext', 'Wrong opening tag'));
                return false;
            }
            $pos = $tagEndPos + 1;
            $tagString = substr($data, $tagBeginPos + 1, $tagEndPos - $tagBeginPos - 1);
            // Check for final backslash
            $noChildren = substr($tagString, -1, 1) == '/' ? true : false;
            // Remove final backslash and spaces
            $tagString = preg_replace("/\\s*\\/\$/", "", $tagString);
            $firstSpacePos = strpos($tagString, ' ');
            if ($firstSpacePos === false) {
                $tagName = strtolower(trim($tagString));
                $attributeString = '';
            } else {
                $tagName = strtolower(substr($tagString, 0, $firstSpacePos));
                $attributeString = substr($tagString, $firstSpacePos + 1);
                $attributeString = trim($attributeString);
                // Parse attribute string
                if ($attributeString) {
                    $attributes = $this->parseAttributes($attributeString);
                }
            }
            // Determine tag's name
            if (isset($this->InputTags[$tagName])) {
                $thisInputTag = $this->InputTags[$tagName];
                if (isset($thisInputTag['name'])) {
                    $newTagName = $thisInputTag['name'];
                } else {
                    $newTagName = $this->callInputHandler('nameHandler', $tagName, $attributes);
                }
            } else {
                if ($this->XMLSchema->exists($tagName)) {
                    $newTagName = $tagName;
                } else {
                    $this->handleError(self::ERROR_SYNTAX, ezpI18n::tr('kernel/classes/datatypes/ezxmltext', 'Unknown tag: &lt;%1&gt;.', false, array($tagName)));
                    return false;
                }
            }
            // Check 'noChildren' property
            if (isset($thisInputTag['noChildren'])) {
                $noChildren = true;
            }
            $thisOutputTag = isset($this->OutputTags[$newTagName]) ? $this->OutputTags[$newTagName] : null;
            // Implementation of 'autoCloseOn' rule ( Handling of unclosed tags, ex.: <p>, <li> )
            if (isset($thisOutputTag['autoCloseOn']) && $parent && $parent->parentNode instanceof DOMElement && in_array($parent->nodeName, $thisOutputTag['autoCloseOn'])) {
                // Wrong nesting: auto-close parent and try to re-parse this tag at higher level
                array_pop($this->ParentStack);
                $pos = $tagBeginPos;
                return true;
            }
            // Append to parent stack
            if (!$noChildren && $newTagName !== false) {
                $this->ParentStack[] = array($tagName, $newTagName, $attributeString);
            }
            if (!$newTagName) {
                // If $newTagName is an empty string then it's not a error
                if ($newTagName === false) {
                    $this->handleError(self::ERROR_SYNTAX, ezpI18n::tr('kernel/classes/datatypes/ezxmltext', "Can't convert tag's name: &lt;%1&gt;.", false, array($tagName)));
                }
                return false;
            }
            // wordmatch.ini support
            if ($attributeString) {
                $attributes = $this->wordMatchSupport($newTagName, $attributes, $attributeString);
            }
        }
        // Create text or normal node.
        if ($newTagName == '#text') {
            $element = $this->Document->createTextNode($textContent);
        } else {
            $element = $this->Document->createElement($newTagName);
        }
        if ($attributes) {
            $this->setAttributes($element, $attributes);
        }
        // Append element as a child or set it as root if there is no parent.
        if ($parent) {
            $parent->appendChild($element);
        } else {
            $this->Document->appendChild($element);
        }
        $params = array();
        $params[] =& $data;
        $params[] =& $pos;
        $params[] =& $tagBeginPos;
        $result = $this->callOutputHandler('parsingHandler', $element, $params);
        if ($result === false) {
            // This tag is already parsed in handler
            if (!$noChildren) {
                array_pop($this->ParentStack);
            }
            return false;
        }
        if ($this->QuitProcess) {
            return false;
        }
        // Process children
        if (!$noChildren) {
            do {
                $parseResult = $this->parseTag($data, $pos, $element);
                if ($this->QuitProcess) {
                    return false;
                }
            } while ($parseResult !== true);
        }
        return false;
    }