diff options
Diffstat (limited to 'src/HTML5/Parser/DOMTreeBuilder.php')
-rw-r--r-- | src/HTML5/Parser/DOMTreeBuilder.php | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/src/HTML5/Parser/DOMTreeBuilder.php b/src/HTML5/Parser/DOMTreeBuilder.php index d2c8020..59504f5 100644 --- a/src/HTML5/Parser/DOMTreeBuilder.php +++ b/src/HTML5/Parser/DOMTreeBuilder.php @@ -301,10 +301,12 @@ class DOMTreeBuilder implements EventHandler ) + $this->nsStack[0]); $pushes ++; } + $needsWorkaround = false; if (isset($this->options["xmlNamespaces"]) && $this->options["xmlNamespaces"]) { // when xmlNamespaces is true a and we found a 'xmlns' or 'xmlns:*' attribute, we should add a new item to the $nsStack foreach ($attributes as $aName => $aVal) { if ($aName === 'xmlns') { + $needsWorkaround = $aVal; array_unshift($this->nsStack, array( '' => $aVal ) + $this->nsStack[0]); @@ -321,17 +323,29 @@ class DOMTreeBuilder implements EventHandler try { $prefix = ($pos = strpos($lname, ':')) ? substr($lname, 0, $pos) : ''; - if (isset($this->nsStack[0][$prefix])) { - $ele = $this->doc->createElementNS($this->nsStack[0][$prefix], $lname); + + if ($needsWorkaround!==false) { + + $xml = "<$lname xmlns=\"$needsWorkaround\" ".(strlen($prefix) && isset($this->nsStack[0][$prefix])?("xmlns:$prefix=\"".$this->nsStack[0][$prefix]."\""):"")."/>"; + + $frag = new \DOMDocument('1.0', 'UTF-8'); + $frag->loadXML($xml); + + $ele = $this->doc->importNode($frag->documentElement, true); + } else { - $ele = $this->doc->createElement($lname); + if (isset($this->nsStack[0][$prefix])) { + $ele = $this->doc->createElementNS($this->nsStack[0][$prefix], $lname); + } else { + $ele = $this->doc->createElement($lname); + } } + } catch (\DOMException $e) { $this->parseError("Illegal tag name: <$lname>. Replaced with <invalid>."); $ele = $this->doc->createElement('invalid'); } - // when we add some namespacess, we have to track them. Later, when "endElement" is invoked, we have to remove them if ($pushes > 0) { // PHP tends to free the memory used by DOM, @@ -346,6 +360,10 @@ class DOMTreeBuilder implements EventHandler } foreach ($attributes as $aName => $aVal) { + // xmlns attributes can't be set + if ($aName === 'xmlns') { + continue; + } if ($this->insertMode == static::IM_IN_SVG) { $aName = Elements::normalizeSvgAttribute($aName); @@ -355,11 +373,11 @@ class DOMTreeBuilder implements EventHandler try { $prefix = ($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : false; - if ($prefix!==false && $prefix !== 'xmlns' && isset($this->nsStack[0][$prefix])) { + + if ($prefix==='xmlns') { + $ele->setAttributeNs(self::NAMESPACE_XMLNS, $aName, $aVal); + } elseif ($prefix!==false && isset($this->nsStack[0][$prefix])) { $ele->setAttributeNs($this->nsStack[0][$prefix], $aName, $aVal); - } elseif ($aName === 'xmlns') { - // setAttribute('xmlns', '..') is not possible, so we have to add a fake attribute - $ele->setAttribute("xmlns:x___xmlns__x", $aVal); } else { $ele->setAttribute($aName, $aVal); } |