| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681 |
- <?php
- /**
- * DOMDocumentWrapper class simplifies work with DOMDocument.
- *
- * Know bug:
- * - in XHTML fragments, <br /> changes to <br clear="none" />
- *
- * @todo check XML catalogs compatibility
- * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
- * @package phpQuery
- */
- class DOMDocumentWrapper {
- /**
- * @var DOMDocument
- */
- public $document;
- public $id;
- /**
- * @todo Rewrite as method and quess if null.
- * @var unknown_type
- */
- public $contentType = '';
- public $xpath;
- public $uuid = 0;
- public $data = array();
- public $dataNodes = array();
- public $events = array();
- public $eventsNodes = array();
- public $eventsGlobal = array();
- /**
- * @TODO iframes support http://code.google.com/p/phpquery/issues/detail?id=28
- * @var unknown_type
- */
- public $frames = array();
- /**
- * Document root, by default equals to document itself.
- * Used by documentFragments.
- *
- * @var DOMNode
- */
- public $root;
- public $isDocumentFragment;
- public $isXML = false;
- public $isXHTML = false;
- public $isHTML = false;
- public $charset;
- public function __construct($markup = null, $contentType = null, $newDocumentID = null) {
- if (isset($markup))
- $this->load($markup, $contentType, $newDocumentID);
- $this->id = $newDocumentID
- ? $newDocumentID
- : md5(microtime());
- }
- public function load($markup, $contentType = null, $newDocumentID = null) {
- // phpQuery::$documents[$id] = $this;
- $this->contentType = strtolower($contentType);
- if ($markup instanceof DOMDOCUMENT) {
- $this->document = $markup;
- $this->root = $this->document;
- $this->charset = $this->document->encoding;
- // TODO isDocumentFragment
- $loaded = true;
- } else {
- $loaded = $this->loadMarkup($markup);
- }
- if ($loaded) {
- // $this->document->formatOutput = true;
- $this->document->preserveWhiteSpace = true;
- $this->xpath = new DOMXPath($this->document);
- $this->afterMarkupLoad();
- return true;
- // remember last loaded document
- // return phpQuery::selectDocument($id);
- }
- return false;
- }
- protected function afterMarkupLoad() {
- if ($this->isXHTML) {
- $this->xpath->registerNamespace("html", "http://www.w3.org/1999/xhtml");
- }
- }
- protected function loadMarkup($markup) {
- $loaded = false;
- if ($this->contentType) {
- self::debug("Load markup for content type {$this->contentType}");
- // content determined by contentType
- list($contentType, $charset) = $this->contentTypeToArray($this->contentType);
- switch($contentType) {
- case 'text/html':
- phpQuery::debug("Loading HTML, content type '{$this->contentType}'");
- $loaded = $this->loadMarkupHTML($markup, $charset);
- break;
- case 'text/xml':
- case 'application/xhtml+xml':
- phpQuery::debug("Loading XML, content type '{$this->contentType}'");
- $loaded = $this->loadMarkupXML($markup, $charset);
- break;
- default:
- // for feeds or anything that sometimes doesn't use text/xml
- if (strpos('xml', $this->contentType) !== false) {
- phpQuery::debug("Loading XML, content type '{$this->contentType}'");
- $loaded = $this->loadMarkupXML($markup, $charset);
- } else
- phpQuery::debug("Could not determine document type from content type '{$this->contentType}'");
- }
- } else {
- // content type autodetection
- if ($this->isXML($markup)) {
- phpQuery::debug("Loading XML, isXML() == true");
- $loaded = $this->loadMarkupXML($markup);
- if (! $loaded && $this->isXHTML) {
- phpQuery::debug('Loading as XML failed, trying to load as HTML, isXHTML == true');
- $loaded = $this->loadMarkupHTML($markup);
- }
- } else {
- phpQuery::debug("Loading HTML, isXML() == false");
- $loaded = $this->loadMarkupHTML($markup);
- }
- }
- return $loaded;
- }
- protected function loadMarkupReset() {
- $this->isXML = $this->isXHTML = $this->isHTML = false;
- }
- protected function documentCreate($charset, $version = '1.0') {
- if (! $version)
- $version = '1.0';
- $this->document = new DOMDocument($version, $charset);
- $this->charset = $this->document->encoding;
- // $this->document->encoding = $charset;
- $this->document->formatOutput = true;
- $this->document->preserveWhiteSpace = true;
- }
- protected function loadMarkupHTML($markup, $requestedCharset = null) {
- if (phpQuery::$debug)
- phpQuery::debug('Full markup load (HTML): '.substr($markup, 0, 250));
- $this->loadMarkupReset();
- $this->isHTML = true;
- if (!isset($this->isDocumentFragment))
- $this->isDocumentFragment = self::isDocumentFragmentHTML($markup);
- $charset = null;
- $documentCharset = $this->charsetFromHTML($markup);
- $addDocumentCharset = false;
- if ($documentCharset) {
- $charset = $documentCharset;
- $markup = $this->charsetFixHTML($markup);
- } else if ($requestedCharset) {
- $charset = $requestedCharset;
- }
- if (! $charset)
- $charset = phpQuery::$defaultCharset;
- // HTTP 1.1 says that the default charset is ISO-8859-1
- // @see http://www.w3.org/International/O-HTTP-charset
- if (! $documentCharset) {
- $documentCharset = 'ISO-8859-1';
- $addDocumentCharset = true;
- }
- // Should be careful here, still need 'magic encoding detection' since lots of pages have other 'default encoding'
- // Worse, some pages can have mixed encodings... we'll try not to worry about that
- $requestedCharset = strtoupper($requestedCharset);
- $documentCharset = strtoupper($documentCharset);
- phpQuery::debug("DOC: $documentCharset REQ: $requestedCharset");
- if ($requestedCharset && $documentCharset && $requestedCharset !== $documentCharset) {
- phpQuery::debug("CHARSET CONVERT");
- // Document Encoding Conversion
- // http://code.google.com/p/phpquery/issues/detail?id=86
- if (function_exists('mb_detect_encoding')) {
- $possibleCharsets = array($documentCharset, $requestedCharset, 'AUTO');
- $docEncoding = mb_detect_encoding($markup, implode(', ', $possibleCharsets));
- if (! $docEncoding)
- $docEncoding = $documentCharset; // ok trust the document
- phpQuery::debug("DETECTED '$docEncoding'");
- // Detected does not match what document says...
- if ($docEncoding !== $documentCharset) {
- // Tricky..
- }
- if ($docEncoding !== $requestedCharset) {
- phpQuery::debug("CONVERT $docEncoding => $requestedCharset");
- $markup = mb_convert_encoding($markup, $requestedCharset, $docEncoding);
- $markup = $this->charsetAppendToHTML($markup, $requestedCharset);
- $charset = $requestedCharset;
- }
- } else {
- phpQuery::debug("TODO: charset conversion without mbstring...");
- }
- }
- $return = false;
- if ($this->isDocumentFragment) {
- phpQuery::debug("Full markup load (HTML), DocumentFragment detected, using charset '$charset'");
- $return = $this->documentFragmentLoadMarkup($this, $charset, $markup);
- } else {
- if ($addDocumentCharset) {
- phpQuery::debug("Full markup load (HTML), appending charset: '$charset'");
- $markup = $this->charsetAppendToHTML($markup, $charset);
- }
- phpQuery::debug("Full markup load (HTML), documentCreate('$charset')");
- $this->documentCreate($charset);
- $return = phpQuery::$debug === 2
- ? $this->document->loadHTML($markup)
- : @$this->document->loadHTML($markup);
- if ($return)
- $this->root = $this->document;
- }
- if ($return && ! $this->contentType)
- $this->contentType = 'text/html';
- return $return;
- }
- protected function loadMarkupXML($markup, $requestedCharset = null) {
- if (phpQuery::$debug)
- phpQuery::debug('Full markup load (XML): '.substr($markup, 0, 250));
- $this->loadMarkupReset();
- $this->isXML = true;
- // check agains XHTML in contentType or markup
- $isContentTypeXHTML = $this->isXHTML();
- $isMarkupXHTML = $this->isXHTML($markup);
- if ($isContentTypeXHTML || $isMarkupXHTML) {
- self::debug('Full markup load (XML), XHTML detected');
- $this->isXHTML = true;
- }
- // determine document fragment
- if (! isset($this->isDocumentFragment))
- $this->isDocumentFragment = $this->isXHTML
- ? self::isDocumentFragmentXHTML($markup)
- : self::isDocumentFragmentXML($markup);
- // this charset will be used
- $charset = null;
- // charset from XML declaration @var string
- $documentCharset = $this->charsetFromXML($markup);
- if (! $documentCharset) {
- if ($this->isXHTML) {
- // this is XHTML, try to get charset from content-type meta header
- $documentCharset = $this->charsetFromHTML($markup);
- if ($documentCharset) {
- phpQuery::debug("Full markup load (XML), appending XHTML charset '$documentCharset'");
- $this->charsetAppendToXML($markup, $documentCharset);
- $charset = $documentCharset;
- }
- }
- if (! $documentCharset) {
- // if still no document charset...
- $charset = $requestedCharset;
- }
- } else if ($requestedCharset) {
- $charset = $requestedCharset;
- }
- if (! $charset) {
- $charset = phpQuery::$defaultCharset;
- }
- if ($requestedCharset && $documentCharset && $requestedCharset != $documentCharset) {
- // TODO place for charset conversion
- // $charset = $requestedCharset;
- }
- $return = false;
- if ($this->isDocumentFragment) {
- phpQuery::debug("Full markup load (XML), DocumentFragment detected, using charset '$charset'");
- $return = $this->documentFragmentLoadMarkup($this, $charset, $markup);
- } else {
- // FIXME ???
- if ($isContentTypeXHTML && ! $isMarkupXHTML)
- if (! $documentCharset) {
- phpQuery::debug("Full markup load (XML), appending charset '$charset'");
- $markup = $this->charsetAppendToXML($markup, $charset);
- }
- // see http://pl2.php.net/manual/en/book.dom.php#78929
- // LIBXML_DTDLOAD (>= PHP 5.1)
- // does XML ctalogues works with LIBXML_NONET
- // $this->document->resolveExternals = true;
- // TODO test LIBXML_COMPACT for performance improvement
- // create document
- $this->documentCreate($charset);
- if (phpversion() < 5.1) {
- $this->document->resolveExternals = true;
- $return = phpQuery::$debug === 2
- ? $this->document->loadXML($markup)
- : @$this->document->loadXML($markup);
- } else {
- /** @link http://pl2.php.net/manual/en/libxml.constants.php */
- $libxmlStatic = phpQuery::$debug === 2
- ? LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET
- : LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET|LIBXML_NOWARNING|LIBXML_NOERROR;
- $return = $this->document->loadXML($markup, $libxmlStatic);
- // if (! $return)
- // $return = $this->document->loadHTML($markup);
- }
- if ($return)
- $this->root = $this->document;
- }
- if ($return) {
- if (! $this->contentType) {
- if ($this->isXHTML)
- $this->contentType = 'application/xhtml+xml';
- else
- $this->contentType = 'text/xml';
- }
- return $return;
- } else {
- throw new Exception("Error loading XML markup");
- }
- }
- protected function isXHTML($markup = null) {
- if (! isset($markup)) {
- return strpos($this->contentType, 'xhtml') !== false;
- }
- // XXX ok ?
- return strpos($markup, "<!DOCTYPE html") !== false;
- // return stripos($doctype, 'xhtml') !== false;
- // $doctype = isset($dom->doctype) && is_object($dom->doctype)
- // ? $dom->doctype->publicId
- // : self::$defaultDoctype;
- }
- protected function isXML($markup) {
- // return strpos($markup, '<?xml') !== false && stripos($markup, 'xhtml') === false;
- return strpos(substr($markup, 0, 100), '<'.'?xml') !== false;
- }
- protected function contentTypeToArray($contentType) {
- $test = null;
- $test =
- $matches = explode(';', trim(strtolower($contentType)));
- if (isset($matches[1])) {
- $matches[1] = explode('=', $matches[1]);
- // strip 'charset='
- $matches[1] = isset($matches[1][1]) && trim($matches[1][1])
- ? $matches[1][1]
- : $matches[1][0];
- } else
- $matches[1] = null;
- return $matches;
- }
- /**
- *
- * @param $markup
- * @return array contentType, charset
- */
- protected function contentTypeFromHTML($markup) {
- $matches = array();
- // find meta tag
- preg_match('@<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i',
- $markup, $matches
- );
- if (! isset($matches[0]))
- return array(null, null);
- // get attr 'content'
- preg_match('@content\\s*=\\s*(["|\'])(.+?)\\1@', $matches[0], $matches);
- if (! isset($matches[0]))
- return array(null, null);
- return $this->contentTypeToArray($matches[2]);
- }
- protected function charsetFromHTML($markup) {
- $contentType = $this->contentTypeFromHTML($markup);
- return $contentType[1];
- }
- protected function charsetFromXML($markup) {
- $matches;
- // find declaration
- preg_match('@<'.'?xml[^>]+encoding\\s*=\\s*(["|\'])(.*?)\\1@i',
- $markup, $matches
- );
- return isset($matches[2])
- ? strtolower($matches[2])
- : null;
- }
- /**
- * Repositions meta[type=charset] at the start of head. Bypasses DOMDocument bug.
- *
- * @link http://code.google.com/p/phpquery/issues/detail?id=80
- * @param $html
- */
- protected function charsetFixHTML($markup) {
- $matches = array();
- // find meta tag
- preg_match('@\s*<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i',
- $markup, $matches, PREG_OFFSET_CAPTURE
- );
- if (! isset($matches[0]))
- return;
- $metaContentType = $matches[0][0];
- $markup = substr($markup, 0, $matches[0][1])
- .substr($markup, $matches[0][1]+strlen($metaContentType));
- $headStart = stripos($markup, '<head>');
- $markup = substr($markup, 0, $headStart+6).$metaContentType
- .substr($markup, $headStart+6);
- return $markup;
- }
- protected function charsetAppendToHTML($html, $charset, $xhtml = false) {
- // remove existing meta[type=content-type]
- $html = preg_replace('@\s*<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', '', $html);
- $meta = '<meta http-equiv="Content-Type" content="text/html;charset='
- .$charset.'" '
- .($xhtml ? '/' : '')
- .'>';
- if (strpos($html, '<head') === false) {
- if (strpos($html, '<html') === false) {
- return $meta.$html;
- } else {
- return preg_replace(
- '@<html(.*?)(?(?<!\?)>)@s',
- "<html\\1><head>{$meta}</head>",
- $html
- );
- }
- } else {
- return preg_replace(
- '@<head(.*?)(?(?<!\?)>)@s',
- '<head\\1>'.$meta,
- $html
- );
- }
- }
- protected function charsetAppendToXML($markup, $charset) {
- $declaration = '<'.'?xml version="1.0" encoding="'.$charset.'"?'.'>';
- return $declaration.$markup;
- }
- public static function isDocumentFragmentHTML($markup) {
- return stripos($markup, '<html') === false && stripos($markup, '<!doctype') === false;
- }
- public static function isDocumentFragmentXML($markup) {
- return stripos($markup, '<'.'?xml') === false;
- }
- public static function isDocumentFragmentXHTML($markup) {
- return self::isDocumentFragmentHTML($markup);
- }
- public function importAttr($value) {
- // TODO
- }
- /**
- *
- * @param $source
- * @param $target
- * @param $sourceCharset
- * @return array Array of imported nodes.
- */
- public function import($source, $sourceCharset = null) {
- // TODO charset conversions
- $return = array();
- if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST))
- $source = array($source);
- // if (is_array($source)) {
- // foreach($source as $node) {
- // if (is_string($node)) {
- // // string markup
- // $fake = $this->documentFragmentCreate($node, $sourceCharset);
- // if ($fake === false)
- // throw new Exception("Error loading documentFragment markup");
- // else
- // $return = array_merge($return,
- // $this->import($fake->root->childNodes)
- // );
- // } else {
- // $return[] = $this->document->importNode($node, true);
- // }
- // }
- // return $return;
- // } else {
- // // string markup
- // $fake = $this->documentFragmentCreate($source, $sourceCharset);
- // if ($fake === false)
- // throw new Exception("Error loading documentFragment markup");
- // else
- // return $this->import($fake->root->childNodes);
- // }
- if (is_array($source) || $source instanceof DOMNODELIST) {
- // dom nodes
- self::debug('Importing nodes to document');
- foreach($source as $node)
- $return[] = $this->document->importNode($node, true);
- } else {
- // string markup
- $fake = $this->documentFragmentCreate($source, $sourceCharset);
- if ($fake === false)
- throw new Exception("Error loading documentFragment markup");
- else
- return $this->import($fake->root->childNodes);
- }
- return $return;
- }
- /**
- * Creates new document fragment.
- *
- * @param $source
- * @return DOMDocumentWrapper
- */
- protected function documentFragmentCreate($source, $charset = null) {
- $fake = new DOMDocumentWrapper();
- $fake->contentType = $this->contentType;
- $fake->isXML = $this->isXML;
- $fake->isHTML = $this->isHTML;
- $fake->isXHTML = $this->isXHTML;
- $fake->root = $fake->document;
- if (! $charset)
- $charset = $this->charset;
- // $fake->documentCreate($this->charset);
- if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST))
- $source = array($source);
- if (is_array($source) || $source instanceof DOMNODELIST) {
- // dom nodes
- // load fake document
- if (! $this->documentFragmentLoadMarkup($fake, $charset))
- return false;
- $nodes = $fake->import($source);
- foreach($nodes as $node)
- $fake->root->appendChild($node);
- } else {
- // string markup
- $this->documentFragmentLoadMarkup($fake, $charset, $source);
- }
- return $fake;
- }
- /**
- *
- * @param $document DOMDocumentWrapper
- * @param $markup
- * @return $document
- */
- private function documentFragmentLoadMarkup($fragment, $charset, $markup = null) {
- // TODO error handling
- // TODO copy doctype
- // tempolary turn off
- $fragment->isDocumentFragment = false;
- if ($fragment->isXML) {
- if ($fragment->isXHTML) {
- // add FAKE element to set default namespace
- $fragment->loadMarkupXML('<?xml version="1.0" encoding="'.$charset.'"?>'
- .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
- .'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
- .'<fake xmlns="http://www.w3.org/1999/xhtml">'.$markup.'</fake>');
- $fragment->root = $fragment->document->firstChild->nextSibling;
- } else {
- $fragment->loadMarkupXML('<?xml version="1.0" encoding="'.$charset.'"?><fake>'.$markup.'</fake>');
- $fragment->root = $fragment->document->firstChild;
- }
- } else {
- $markup2 = phpQuery::$defaultDoctype.'<html><head><meta http-equiv="Content-Type" content="text/html;charset='
- .$charset.'"></head>';
- $noBody = strpos($markup, '<body') === false;
- if ($noBody)
- $markup2 .= '<body>';
- $markup2 .= $markup;
- if ($noBody)
- $markup2 .= '</body>';
- $markup2 .= '</html>';
- $fragment->loadMarkupHTML($markup2);
- // TODO resolv body tag merging issue
- $fragment->root = $noBody
- ? $fragment->document->firstChild->nextSibling->firstChild->nextSibling
- : $fragment->document->firstChild->nextSibling->firstChild->nextSibling;
- }
- if (! $fragment->root)
- return false;
- $fragment->isDocumentFragment = true;
- return true;
- }
- protected function documentFragmentToMarkup($fragment) {
- phpQuery::debug('documentFragmentToMarkup');
- $tmp = $fragment->isDocumentFragment;
- $fragment->isDocumentFragment = false;
- $markup = $fragment->markup();
- if ($fragment->isXML) {
- $markup = substr($markup, 0, strrpos($markup, '</fake>'));
- if ($fragment->isXHTML) {
- $markup = substr($markup, strpos($markup, '<fake')+43);
- } else {
- $markup = substr($markup, strpos($markup, '<fake>')+6);
- }
- } else {
- $markup = substr($markup, strpos($markup, '<body>')+6);
- $markup = substr($markup, 0, strrpos($markup, '</body>'));
- }
- $fragment->isDocumentFragment = $tmp;
- if (phpQuery::$debug)
- phpQuery::debug('documentFragmentToMarkup: '.substr($markup, 0, 150));
- return $markup;
- }
- /**
- * Return document markup, starting with optional $nodes as root.
- *
- * @param $nodes DOMNode|DOMNodeList
- * @return string
- */
- public function markup($nodes = null, $innerMarkup = false) {
- if (isset($nodes) && count($nodes) == 1 && $nodes[0] instanceof DOMDOCUMENT)
- $nodes = null;
- if (isset($nodes)) {
- $markup = '';
- if (!is_array($nodes) && !($nodes instanceof DOMNODELIST) )
- $nodes = array($nodes);
- if ($this->isDocumentFragment && ! $innerMarkup)
- foreach($nodes as $i => $node)
- if ($node->isSameNode($this->root)) {
- // var_dump($node);
- $nodes = array_slice($nodes, 0, $i)
- + phpQuery::DOMNodeListToArray($node->childNodes)
- + array_slice($nodes, $i+1);
- }
- if ($this->isXML && ! $innerMarkup) {
- self::debug("Getting outerXML with charset '{$this->charset}'");
- // we need outerXML, so we can benefit from
- // $node param support in saveXML()
- foreach($nodes as $node)
- $markup .= $this->document->saveXML($node);
- } else {
- $loop = array();
- if ($innerMarkup)
- foreach($nodes as $node) {
- if ($node->childNodes)
- foreach($node->childNodes as $child)
- $loop[] = $child;
- else
- $loop[] = $node;
- }
- else
- $loop = $nodes;
- self::debug("Getting markup, moving selected nodes (".count($loop).") to new DocumentFragment");
- $fake = $this->documentFragmentCreate($loop);
- $markup = $this->documentFragmentToMarkup($fake);
- }
- if ($this->isXHTML) {
- self::debug("Fixing XHTML");
- $markup = self::markupFixXHTML($markup);
- }
- self::debug("Markup: ".substr($markup, 0, 250));
- return $markup;
- } else {
- if ($this->isDocumentFragment) {
- // documentFragment, html only...
- self::debug("Getting markup, DocumentFragment detected");
- // return $this->markup(
- //// $this->document->getElementsByTagName('body')->item(0)
- // $this->document->root, true
- // );
- $markup = $this->documentFragmentToMarkup($this);
- // no need for markupFixXHTML, as it's done thought markup($nodes) method
- return $markup;
- } else {
- self::debug("Getting markup (".($this->isXML?'XML':'HTML')."), final with charset '{$this->charset}'");
- $markup = $this->isXML
- ? $this->document->saveXML()
- : $this->document->saveHTML();
- if ($this->isXHTML) {
- self::debug("Fixing XHTML");
- $markup = self::markupFixXHTML($markup);
- }
- self::debug("Markup: ".substr($markup, 0, 250));
- return $markup;
- }
- }
- }
- protected static function markupFixXHTML($markup) {
- $markup = self::expandEmptyTag('script', $markup);
- $markup = self::expandEmptyTag('select', $markup);
- $markup = self::expandEmptyTag('textarea', $markup);
- return $markup;
- }
- public static function debug($text) {
- phpQuery::debug($text);
- }
- /**
- * expandEmptyTag
- *
- * @param $tag
- * @param $xml
- * @return string
- * @author mjaque at ilkebenson dot com
- * @link http://php.net/manual/en/domdocument.savehtml.php#81256
- */
- public static function expandEmptyTag($tag, $xml){
- $indice = 0;
- while ($indice< strlen($xml)){
- $pos = strpos($xml, "<$tag ", $indice);
- if ($pos){
- $posCierre = strpos($xml, ">", $pos);
- if ($xml[$posCierre-1] == "/"){
- $xml = substr_replace($xml, "></$tag>", $posCierre-1, 2);
- }
- $indice = $posCierre;
- }
- else break;
- }
- return $xml;
- }
- }
|