diff --git a/src/XMLBuild.php b/src/XMLBuild.php index dce4562..8db197e 100644 --- a/src/XMLBuild.php +++ b/src/XMLBuild.php @@ -100,7 +100,7 @@ public static function attributeValue($value) // REC-xml/#AVNormalize - preserve // REC-xml/#sec-line-ends - preserve - $buffer = preg_replace_callback('~\r\n|\r(?!\n)|\t~', array('self', 'numericEntitiesSingleByte'), $buffer); + $buffer = preg_replace_callback('~\r\n|\r(?!\n)|\t~', array('XMLBuild', 'numericEntitiesSingleByte'), $buffer); return htmlspecialchars($buffer, ENT_QUOTES, 'UTF-8', false); } diff --git a/src/XMLReaderNode.php b/src/XMLReaderNode.php index 0ef42e1..9ca4241 100644 --- a/src/XMLReaderNode.php +++ b/src/XMLReaderNode.php @@ -99,6 +99,37 @@ public function getSimpleXMLElement($className = null) return $this->simpleXML; } + /** + * Like {@see getSimpleXMLElement()} but strips all XML namespace declarations + * from the serialized node before parsing, so that plain XPath expressions + * (e.g. ./code) work on feeds that carry a default xmlns="..." attribute. + * + * @return SimpleXMLElement|null + */ + public function getSimpleXMLElementWithoutNamespaces(): ?\SimpleXMLElement + { + if ($this->reader->nodeType !== XMLReader::ELEMENT) { + return null; + } + + $doc = new \DOMDocument(); + $node = $this->expand($doc); + $xml = $doc->saveXML($node); + + if (false === $xml) { + return null; + } + + $xml = preg_replace('/\s+xmlns(?::\w+)?="[^"]*"/', '', $xml); + if (null === $xml) { + return null; + } + + $element = simplexml_load_string($xml); + + return $element instanceof \SimpleXMLElement ? $element : null; + } + /** * @deprecated since v0.1.4, use {@see getSimpleXMLElement()} instead * @return null|SimpleXMLElement @@ -212,7 +243,7 @@ public function readOuterXml() * @throws BadMethodCallException * @return DOMNode */ - public function expand(DOMNode $baseNode = null) + public function expand(?DOMNode $baseNode = null) { if (null === $baseNode) { $baseNode = new DomDocument();