Extract oembed information from the <link rel="alternate"> elements
Note: Some sites use <meta rel="alternate"> instead.

@param DOMDocument $html

@return string|null
439970
protected static function getEndPointFromDom(DOMDocument $html)
    {
        foreach (['link', 'meta'] as $tagName) {
            foreach ($html->getElementsByTagName($tagName) as $link) {
                $rel = trim(strtolower($link->getAttribute('rel')));
                $href = $link->getAttribute('href');

                if (empty($href)) {
                    continue;
                }

                if ($rel === 'alternate') {
                    switch (strtolower($link->getAttribute('type'))) {
                        case 'application/json+oembed':
                        case 'application/xml+oembed':
                        case 'text/json+oembed':
                        case 'text/xml+oembed':
                            return $href;
                    }
                }
            }
        }
    }
221572
public function htmlToElement($html)
    {
        // Buffer engine used to convert the html string into DOMElements,
        $fabrication = new FabricationEngine;
        $fabrication->run($html);

        // Retrive xpath element from the FabricationEngine.
        $element = $this->query('//html/body')->item(0);

        // Append the new DOM Element(s) to the found DOMElement.
        $element->appendChild(
                $this->importNode(
                        $fabrication->query($this->xpath . '/*')->item(0)
                        , true
                )
        );

        return $element;
    }
355037
public function toText($html)
    {
        $parser = new Parser();

        $xmlParser = xml_parser_create();
        xml_set_element_handler($xmlParser, [$parser, 'startElement'], [$parser, 'endElement']);
        xml_set_character_data_handler($xmlParser, [$parser, 'characterData']);

        $wrappedHtml = "<root>$html</root>";
        $returnStatus = xml_parse($xmlParser, $wrappedHtml, true);

        if (!$returnStatus) {
            return $html;
        }

        return $parser->getText();
    }
834464
public function outerHtml() {
    if (($el = $this->getElement()) === NULL) return NULL;

    return $el->ownerDocument->saveXML($el);
  }
935583
public function convert($html) {
    if (preg_match('/^\s*$/u', $html)) {
      return '';
    }
    $html = '<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"></head>' . $html . '</body></html>';
    $this->dom = new \DOMDocument();
    if (!$this->dom->loadHTML($html)) {
      return NULL;
    }
    $xp = new \DOMXPath($this->dom);
    return implode(self::BLOCK_DELIMITER, $this->getBlocks(
      $xp->query('/html/body')->item(0)->childNodes
    ));
  }
571961
public function extractBody($html)
    {
        $matches = array();
        $result = preg_match('|(.*?)<body[^>]*>(.*)</body>|is', $html, $matches);
        if ($result) {
            // Make sure it's not in a comment
            $comment_start = strrpos($matches[1], '<!--');
            $comment_end   = strrpos($matches[1], '-->');
            if ($comment_start === false ||
                ($comment_end !== false && $comment_end > $comment_start)) {
                return $matches[2];
            }
        }
        return $html;
    }
1276286
public function loadHTML($html)
    {
        $html = str_replace(chr(13), '', $html);
        $html = '<?xml version="1.0" encoding="utf-8" ?><' . $this->PARENT_TAG_NAME . '>' . $html . '</' . $this->PARENT_TAG_NAME . '>';
        if (defined('LIBXML_HTML_NODEFDTD')) {
            return $this->dom->loadHTML($html, LIBXML_HTML_NODEFDTD);
        } else {
            return $this->dom->loadHTML($html);
        }


    }
123451
private function prepareHtmlForDomConversion($html)
    {
        $htmlWithSelfClosingSlashes = $this->ensurePhpUnrecognizedSelfClosingTagsAreXml($html);
        $htmlWithDocumentType = $this->ensureDocumentType($htmlWithSelfClosingSlashes);

        return $this->addContentTypeMetaTag($htmlWithDocumentType);
    }
1070321
private function parseContents(string $html): string
    {
        if (\trim($html) === '') {
            return '';
        }

        // Determine value.
        $this->value = $html;
        if (\preg_match("/(.*)<\/\s*" . $this->name . "\s*>/iU", $html, $valueMatches) === 1) {
            $this->value = $valueMatches[1];
        }

        // Don't parse contents of "iframe" element.
        if ($this->name === 'iframe') {
            return $this->parseNoContents('iframe', $html);
        }

        // Only TEXT inside a "script" element.
        if ($this->name === 'script') {
            return $this->parseForeignContents('script', $html);
        }

        // Only TEXT inside a "style" element.
        if ($this->name === 'style') {
            return $this->parseForeignContents('style', $html);
        }

        // Parse contents one token at a time.
        $remainingHtml = $html;
        while ($this->isAnotherTokenPresent($remainingHtml)) {
            $token = Tokenizer::buildFromHtml($remainingHtml, $this);

            if (!$token instanceof TokenInterface || $token->isClosingElementImplied($remainingHtml)) {
                return $remainingHtml;
            }

            $remainingHtml = $token->parse($remainingHtml);
            $this->children[] = $token;
        }

        $this->removeLastTokenIfContainsOnlyWhitespace();

        // Remove remaining closing tag.
        $posOfClosingBracket = \mb_strpos($remainingHtml, '>');

        return \mb_substr($remainingHtml, $posOfClosingBracket + 1);
    }
438408
public static function getJSNodes(DOMDocument $dom)
	{
		$regexp = '/^(?:data-s9e-livepreview-postprocess$|on)/i';
		$nodes  = array_merge(
			self::getAttributesByRegexp($dom, $regexp),
			self::getElementsByRegexp($dom, '/^script$/i')
		);

		return $nodes;
	}
1282348
private function getNodeContent(\DOMNode $node)
    {
        $type = $node->attributes->getNamedItem('type');
        if ($type && strtolower($type->nodeValue) == 'xhtml') {
            $result = '';
            foreach ($node->childNodes as $childNode) {
                $result .= $node->ownerDocument->save($childNode);
            }
            return $result;
        } else {
            return $node->nodeValue;
        }
    }
1056442
private function extractToken($html)
    {
        $token = null;

		$regex = '#<input type="hidden" name="token" value="(.*?)" />#s';

		if (preg_match($regex, $html, $matches) === 1)
		{
			$token = $matches[1];
		}

        return $token;
    }
1265820
protected function getLicenseAttribution( $html ) {
		$meta = [];

		// get license attribution statement if it exists
		preg_match( '/(?:<div class="license-attribution[^>]*>)(.*)(<\/div>)/isU', $html, $matches );

		if ( ! empty( $matches[1] ) ) {
			$html5 = new HtmlParser();
			$dom = $html5->loadHTML( $matches[1] );
			$meta = $this->scrapeAndKneadMeta( $dom );
		}
		return $meta;
	}
468350
static function getDocument($html, $ignore_error = false) {

		$doc = new \DOMDocument();

		$html = trim($html);

		if (!$html) {
			// DOMDocument doesn't support empty value and throws an error
			// Return empty document instead
			return $doc;
		}

		if ($html[0] !== '<') {
			// If HTML does not begin with a tag, we put a body tag around it.
			// If we do not do this, PHP will insert a paragraph tag around
			// the first block of text for some reason which can mess up
			// the newlines. See pre.html test for an example.
			$html = '<body>' . $html . '</body>';
		}

		if ($ignore_error) {
			$doc->strictErrorChecking = false;
			$doc->recover = true;
			$doc->xmlStandalone = true;
			$old_internal_errors = libxml_use_internal_errors(true);
			$load_result = $doc->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE);
			libxml_use_internal_errors($old_internal_errors);
		}
		else {
			$load_result = $doc->loadHTML($html);
		}

		if (!$load_result) {
			throw new Html2TextException("Could not load HTML - badly formed?", $html);
		}

		return $doc;
	}
1076786
public function plain($html)
    {
        $plain = preg_replace('#<br\s*/?>#iu', "\n", $html);
        $plain = strip_tags($plain);
        $plain = html_entity_decode($plain, ENT_QUOTES | ENT_HTML5);

        return $plain;
    }
1318471
private static function convertHtmlToDom($html)
    {
        $dom = new DOMDocument;

        \libxml_use_internal_errors(true);
        $dom->loadHTML($html);

        \libxml_clear_errors();

        return $dom;
    }
894834
public function render($html = null) {
		if ($this->_tagCached === null) {
			$tag = '<' . $this->_tag;
			
			// Classes
			if (! empty($this->_classes)) {
				$this->setAttr(
					self::ATTR_CLASS,
					implode(' ', $this->_classes)
				);
			}

			// Style
			if (! empty($this->_style)) {
				$style = [];
				
				foreach ($this->_style as $param => $value) {
					$style[] = $param . ':' . $value . ';';
				}
				
				$this->setAttr(
					self::ATTR_STYLE,
					implode(' ', $style)
				);
			}

			// Attrs
			if (! empty($this->_attrs)) {
				$attrs = [];
				
				foreach ($this->_attrs as $attr => $value) {
					$attrs[] = $attr . '="' . $value . '"';
				}

				$tag .= ' ' .  implode(' ', $attrs);
			}
			
			$tag .= $this->_closed ? ' />' : '>';
			
			$this->_tagCached = $tag;
		}
		
		if ($this->_closed) {
			return $this->_tagCached;
		}
			
		return $this->_tagCached . ($html === null ? $this->_html : $html) . '</' . $this->_tag . '>';
	}