[
  {
    "path": ".gitignore",
    "content": ".buildpath\n.project\n.settings\n/fDOMDocument-1.1.0.tgz\n.idea\nbuild\ncomposer.lock\ncomposer.phar\nvendor/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: php\n\nsudo: false\n\nphp:\n    - \"5.3\"\n    - \"5.4\"\n    - \"5.5\"\n    - \"5.6\"\n    - \"7.0\"\n    - \"7.1\"\n    - nightly\n#    - hhvm\n\nmatrix:\n  allow_failures:\n    - php: nightly\n#    - php: hhvm\n  fast_finish: true\n\ncache:\n  directories:\n    - $HOME/.composer/cache\n\nnotifications:\n  email: false\n\nbefore_script:\n  - composer self-update\n  - composer install\n  - composer require --dev \"phpunit/phpunit ^4.8.35|^5.6|^6.0\"\n\nscript:\n  - vendor/bin/phpunit --verbose\n"
  },
  {
    "path": "LICENSE",
    "content": "fDOMDocument\n\nCopyright (c) 2010-2012 Arne Blankerts <arne@blankerts.de>\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of Arne Blankerts nor the names of contributors\n  may be used to endorse or promote products derived from this software\n  without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\n"
  },
  {
    "path": "README.md",
    "content": "fDOMDocument\n============\n\n> :warning: **This project is Archived**\n> There will be no new features or general bugfixes. In case you found a security problem, please contact me and I'll consider creating an additional release addressing it. Otherwise no updates are planned. The current (potentially final) release `1.6.7` should work under PHP 5.3.3 - PHP 8.1.\n\nThe classes contained within this repository extend the standard DOM to use exceptions at\nall occasions of errors instead of PHP warnings or notices. They also add various custom methods\nand shortcuts for convenience and to simplify the usage of DOM.\n\nRequirements\n------------\n\n    PHP: 5.3.3 (5.3.0-5.3.2 had serious issues with spl stacked autoloaders)\n    Extensions: dom, libxml\n\n    Aus of 1.6.7, tests will require PHPUnit 8.5 and PHP 7.3+\n\nInstallation\n------------\nApart from cloning this repository, fDOMDocument can be installed using by any of the following methods.\n\n##### Composer\nAs fDOMDocument is a library and does not provide any cli tools, you can only add it to your own project:\n\n    {\n        \"require\": {\n            \"theseer/fdomdocument\": \"^1.6\"\n        }\n    }\n\n\n##### YUM/DNF (Fedora / Redhat / CentOS)\nThe following command will install fDOMDocument via its RPM package:\n\n    sudo yum install php-theseer-fDOMDocument\n\n\nUsage\n-----\n\nfDOMDocument is designed as a drop in replacement for DOMDocument. You can either use the composer generated\nautoloader or the provided one.\n\nUsage Samples\n-------------\n    <?php\n\n    require '/path/to/autoload.php';\n\n    $dom = new TheSeer\\fDOM\\fDOMDocument();\n    try {\n        $dom->loadXML('<?xml version=\"1.0\" ?><root><child name=\"foo\" /></root>');\n    } catch (fDOMException $e) {\n        die($e);\n    }\n\n    $child = $dom->queryOne('//child');\n    print_r($child->getAttribute('name'));\n    print_r($child->getAttribute('missing','DefaultValue'));\n\n    ?>\n\nChangelog\n---------\n##### Release 1.6.7\n* Add `#[\\ReturnTypeWillChange]` attribute to shut up PHP 8.1 notices on return types\n* Fix deprecation notice for passing `NULL` where `int` is expected\n\n##### Release 1.6.6\n* Merge PRs 33+34: Add support for parameter \"asTextNode\" to fDOMElement::appendElement(). \n  fDOMElement::appendElementNS() and fDOMElement::appendElementPrefix\n\n##### Releaes 1.6.5\n* Revert git exports limitations as they cause unwanted side effects\n\n##### Releaes 1.6.4\n* Merge PR 31 to optimize travis builds and git exports (Thanks to @willemstuursma)\n\n##### Releaes 1.6.3\n* Merge PR 29 to fix issues with PHP 7.2\n\n##### Release 1.6.2\n* Handle empty string warings from PHP\n\n##### Release 1.6.1\n* Added Workaround for [HHVM Issue #5412](https://github.com/facebook/hhvm/issues/5412)\n\n##### Release 1.6.0\n* Added ```createElement*``` to ```fDOMEmenet``` and ```fDOMDocumentFragment``` as shortcuts\n* Added ```appendElement*``` to ```fDOMDocumentFragment``` as shortcuts\n* Enhanced the exception messages of save errors with filenames to contain the filename\n* Fixed fDomDocumentFragment::__toString to actually work\n* Updated / Added some tests\n\n##### Release 1.5.0\n* Added ```select``` to ```fDOMDocument```,```fDOMElement``` and ```fDOMNode``` to support\n  CSS Selectors in favor of XPath only to find nodes\n\n* Added ```query``` and ```queryOne``` forwardes to ```fDOMNode```\n\n##### Release 1.4.3\n* Added ```saveXML``` and ```saveHTML``` to ```fDOMNode``` and ```fDOMElement``` as a\n  shortcut to calling those methods on the ownerDocument\n\n##### Release 1.4.2\n* Added ```__toString``` support to ```fDOMNode```, ```fDOMElement```, ```fDOMDocument``` and ```fDOMDocumentFragment```\n\n##### Release 1.4.1\n* Removed unused Interface ```fDOMNodeInterface``` from code base\n\n##### Release 1.4.0\n* Added XPathQuery helper object, allowing for a prepared statement alike API around XPath\n\n##### Release 1.3.2\n* Added ```__clone``` method to reset domxpath object when domdocument gets cloned (Thanks to Markus Ineichen for pointing it out)\n\n##### Release 1.3.1\n* PHP 5.3 compatibility: changed interal behavior for incompatible changes from PHP 5.3 to 5.4 (Thanks to Jens Graefe for pointing it out)\n\n##### Release 1.3.0\n* Added appendTextNode method (Thanks to Markus Ineichen)\n* Added appendElement / appendElementNS to DOMDocument to support documentElement \"creation\" (Thanks to Markus Ineichen)\n* Overwrite createElement / createElementNS to throw exception on error\n* Removed fDOMFilter code: Unmaintained and broken in its current form\n* Added (static) Flag for fDOMException to globally enable full exception message\n* Added Unit tests\n\n##### Release 1.2.4\n* PHP 5.4 compatibilty: added support for optional options bitmask on additional methods\n\n##### Release 1.2.3\n* Cleanup code style to adhere coding standard\n* Added entity support for Attributes\n* Added phpcs file to make coding standard public\n\n##### Release 1.2.2\n* Fix Exception to not overwrite final methods of \\Exception\n\n##### Release 1.2.1\n* Changed fDOMDocument to be no longer final, use lsb to lookup actual class in constructor.\n  This should fix test/mock issues.\n\n##### Release 1.2.0\n* Changed fException to be more compatible with standard exceptions by adding a switch to get full info by getMessage()\n* Merged setAttributes() and setAttributesNS() methods from Andreas\n* Fixed internal registerNamespace variable mixup\n\n##### Release 1.1.0\n* Renamed files to mimic classname cases\n* Fixed inSameDocument to support DOMDocument as well as DOMNodes\n* Added fDOMXPath class providing queryOne(), qoute() and prepare()\n* Adjusted forwarders in fDOMDocument to make use of new object\n* Fixed various return values to statically return true for compatibility with original API\n* Applied Workaround to fix potential problems with lost references to instances of fDOMDocument\n* Support registerPHPFunctions\n* Bump Copyright\n* Added missing docblocks\n\n##### Release 1.0.2\n* Indenting and typo fixes, minor bugfixes\n\n##### Release 1.0.1\n* Bugfix: typehints corrected\n\n##### Release 1.0.0\n* Initial release\n"
  },
  {
    "path": "build.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- Generated by PHP Project Wizard (PPW) 1.0.4 on Fri Mar 11 16:37:31 CET 2011 -->\n\n<project name=\"fDOMDocument\" default=\"build\" basedir=\".\">\n <property name=\"source\" value=\"src\"/>\n\n <target name=\"clean\" description=\"Clean up and create artifact directories\">\n  <delete dir=\"${basedir}/build/api\"/>\n  <delete dir=\"${basedir}/build/code-browser\"/>\n  <delete dir=\"${basedir}/build/coverage\"/>\n  <delete dir=\"${basedir}/build/logs\"/>\n  <delete dir=\"${basedir}/build/pdepend\"/>\n\n  <mkdir dir=\"${basedir}/build/api\"/>\n  <mkdir dir=\"${basedir}/build/code-browser\"/>\n  <mkdir dir=\"${basedir}/build/coverage\"/>\n  <mkdir dir=\"${basedir}/build/logs\"/>\n  <mkdir dir=\"${basedir}/build/pdepend\"/>\n </target>\n\n <target name=\"phpab\">\n  <exec executable=\"phpab\">\n   <arg line='-o src/autoload.php src' />\n  </exec>\n </target>\n\n <target name=\"phpunit\" description=\"Run unit tests using PHPUnit and generates junit.xml and clover.xml\">\n  <exec executable=\"phpunit\" failonerror=\"true\"/>\n </target>\n\n <target name=\"parallelTasks\" description=\"Run the pdepend, phpmd, phpcpd, phpcs, phpdoc and phploc tasks in parallel using a maximum of 2 threads.\">\n  <parallel threadCount=\"2\">\n   <sequential>\n    <antcall target=\"pdepend\"/>\n    <antcall target=\"phpmd\"/>\n   </sequential>\n   <antcall target=\"phpcpd\"/>\n   <antcall target=\"phpcs\"/>\n   <antcall target=\"phploc\"/>\n  </parallel>\n </target>\n\n <target name=\"pdepend\" description=\"Generate jdepend.xml and software metrics charts using PHP_Depend\">\n  <exec executable=\"pdepend\">\n   <arg line=\"--jdepend-xml=${basedir}/build/logs/jdepend.xml\n              --jdepend-chart=${basedir}/build/pdepend/dependencies.svg\n              --overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg\n              ${source}\" />\n  </exec>\n </target>\n\n <target name=\"phpmd\" description=\"Generate pmd.xml using PHPMD\">\n  <exec executable=\"phpmd\">\n   <arg line=\"${source}\n              xml\n              codesize,design,naming,unusedcode\n              --reportfile ${basedir}/build/logs/pmd.xml\" />\n  </exec>\n </target>\n\n <target name=\"phpcpd\" description=\"Generate pmd-cpd.xml using PHPCPD\">\n  <exec executable=\"phpcpd\">\n   <arg line=\"--log-pmd ${basedir}/build/logs/pmd-cpd.xml ${source}\" />\n  </exec>\n </target>\n\n <target name=\"phploc\" description=\"Generate phploc.csv\">\n  <exec executable=\"phploc\">\n   <arg line=\"--log-csv ${basedir}/build/logs/phploc.csv ${source}\" />\n  </exec>\n </target>\n\n <target name=\"phpcs\" description=\"Generate checkstyle.xml using PHP_CodeSniffer\">\n  <exec executable=\"phpcs\" output=\"/dev/null\">\n   <arg line=\"--report=checkstyle\n              --report-file=${basedir}/build/logs/checkstyle.xml\n              --standard=phpcs.xml\n              ${source}\" />\n  </exec>\n </target>\n\n <target name=\"phpcb\" description=\"Aggregate tool output with PHP_CodeBrowser\">\n  <exec executable=\"phpcb\">\n   <arg line=\"--log    ${basedir}/build/logs\n              --source ${source}\n              --output ${basedir}/build/code-browser\" />\n  </exec>\n </target>\n\n <target name=\"build\" depends=\"clean,parallelTasks,phpunit,phpcb\"/>\n</project>\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"theseer/fdomdocument\",\n    \"description\": \"The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.\",\n    \"homepage\": \"https://github.com/theseer/fDOMDocument\",\n    \"license\": \"BSD-3-Clause\",\n    \"authors\": [\n        {\n            \"name\": \"Arne Blankerts\",\n            \"email\": \"arne@blankerts.de\",\n            \"role\": \"lead\"\n        }\n    ],\n    \"support\": {\n        \"issues\": \"https://github.com/theseer/fDOMDocument/issues\"\n    },\n    \"require\": {\n        \"php\": \">=5.3.3\",\n        \"ext-dom\": \"*\",\n        \"lib-libxml\": \"*\"\n    },\n    \"require-dev\": {\n        \"php\": \">=7.3\"\n    },\n    \"autoload\": {\n        \"classmap\": [\n            \"src/\"\n        ]\n    }\n}\n"
  },
  {
    "path": "fDOMDocument.spec",
    "content": "%define _pearDir /usr/share/pear/\n%define _sourcedir src/\n\nSummary: fDOMDocument - An Extension to PHP's standard DOM to add various convenience methods and exceptions by default\nName: fDOMDocument\nVersion: 1.1.0\nRelease: 1\nGroup: System Environment/Libraries\nLicense: Arne Blankerts\nVendor: Arne Blankerts\nURL: https://github.com/theseer/\n#Source:\nProvides: fDOMDocument-%{version}%{release}\n\nBuildRoot: %{_tmppath}/%{name}-%{version}%{release}-root-%(%{__id_u} -n)\nBuildArch: noarch\n\nRequires: php-common, php-dom\n\n%description\nfDOMDocument - An Extension to PHP's standard DOM to add various convenience methods and exceptions by default\n\n%install\n[ \"$RPM_BUILD_ROOT\" != \"/\" ] && rm -rf $RPM_BUILD_ROOT\n\ninstall -m 755 -d $RPM_BUILD_ROOT%{_pearDir}TheSeer\ninstall -m 755 -d $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument\ninstall -m 755 -d $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMFilter\n\ncp %{_sourcedir}fDOMDocument.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMDocument.php\ncp %{_sourcedir}fDOMDocumentFragment.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMDocumentFragment.php\ncp %{_sourcedir}fDOMElement.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMElement.php\ncp %{_sourcedir}fDOMException.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMException.php\ncp %{_sourcedir}fDOMFilter.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMFilter.php\ncp %{_sourcedir}fDOMNode.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMNode.php\ncp %{_sourcedir}fDOMXPath.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMXPath.php\ncp %{_sourcedir}fDOMFilter/xhtml.php $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/fDOMFilter/xhtml.php\n\nphpab -o $RPM_BUILD_ROOT%{_pearDir}TheSeer/fDOMDocument/autoload.php TheSeer/fDOMDocument\n\n%post\n\n%files\n%defattr(-,root,root)\n%dir %{_pearDir}TheSeer/fDOMDocument\n%dir %{_pearDir}TheSeer/fDOMDocument/fDOMFilter\n\n%{_pearDir}TheSeer/fDOMDocument/*\n%{_pearDir}TheSeer/fDOMDocument/fDOMFilter/*\n%{_pearDir}TheSeer/fDOMDocument/autoload.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMDocument.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMDocumentFragment.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMElement.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMException.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMFilter.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMNode.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMXPath.php\n%{_pearDir}TheSeer/fDOMDocument/fDOMFilter/xhtml.php\n\n%changelog\n* Tue Jul 04 2011 Maik 'M4ikT' Thieme <maik.thieme@gmail.com> 1.1.0\n- Initial package release\n"
  },
  {
    "path": "phive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phive xmlns=\"https://phar.io/phive\">\n  <phar name=\"phpunit\" version=\"^8.5\" installed=\"8.5.23\" location=\"./tools/phpunit\" copy=\"false\"/>\n</phive>\n"
  },
  {
    "path": "phpcs.xml",
    "content": "<?xml version=\"1.0\"?>\n<ruleset name=\"Arne\">\n <description>Arne Blankerts' coding standard</description>\n\n <rule ref=\"Generic.CodeAnalysis.ForLoopShouldBeWhileLoop\"/>\n <rule ref=\"Generic.CodeAnalysis.ForLoopWithTestFunctionCall\"/>\n <rule ref=\"Generic.CodeAnalysis.JumbledIncrementer\"/>\n <rule ref=\"Generic.CodeAnalysis.UnconditionalIfStatement\"/>\n <rule ref=\"Generic.CodeAnalysis.UnnecessaryFinalModifier\"/>\n <rule ref=\"Generic.CodeAnalysis.UselessOverridingMethod\"/>\n\n <rule ref=\"Generic.Commenting.Todo\"/>\n\n <rule ref=\"Generic.ControlStructures.InlineControlStructure\"/>\n\n <rule ref=\"Generic.Files.LineEndings\">\n  <properties>\n   <property name=\"eolChar\" value=\"\\n\"/>\n  </properties>\n </rule>\n\n <rule ref=\"Generic.Formatting.DisallowMultipleStatements\"/>\n <rule ref=\"Generic.Formatting.NoSpaceAfterCast\"/>\n\n <rule ref=\"Generic.Functions.OpeningFunctionBraceKernighanRitchie\" />\n <rule ref=\"Generic.Functions.FunctionCallArgumentSpacing\" />\n <rule ref=\"PEAR.Functions.ValidDefaultValue\"/>\n\n <rule ref=\"Generic.NamingConventions.ConstructorName\"/>\n <!-- <rule ref=\"PEAR.NamingConventions.ValidClassName\"/>-->\n\n <rule ref=\"Generic.PHP.DisallowShortOpenTag\"/>\n <rule ref=\"Generic.PHP.NoSilencedErrors\"/>\n\n <rule ref=\"Generic.WhiteSpace.DisallowTabIndent\"/>\n\n <!-- Namespace handling broken, so disabled -->\n <!--<rule ref=\"Generic.WhiteSpace.ScopeIndent\"/>-->\n <rule ref=\"Squiz.WhiteSpace.SuperfluousWhitespace\"/>\n</ruleset>\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/8.5/phpunit.xsd\"\n         backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         verbose=\"true\"\n         bootstrap=\"src/autoload.php\"\n         convertErrorsToExceptions=\"true\"\n         convertDeprecationsToExceptions=\"true\"\n>\n\n  <testsuites>\n    <testsuite name=\"fDOMDocument\">\n      <directory suffix=\".test.php\">tests</directory>\n    </testsuite>\n  </testsuites>\n\n  <logging>\n    <log type=\"coverage-html\" target=\"build/coverage\" lowUpperBound=\"35\" highLowerBound=\"70\"/>\n    <log type=\"coverage-clover\" target=\"build/logs/clover.xml\"/>\n    <log type=\"junit\" target=\"build/logs/junit.xml\" />\n  </logging>\n\n  <filter>\n    <whitelist addUncoveredFilesFromWhitelist=\"true\">\n      <directory suffix=\".php\">src</directory>\n      <exclude>\n        <directory suffix=\".php\">src/bootstrap</directory>\n      </exclude>\n    </whitelist>\n  </filter>\n</phpunit>\n"
  },
  {
    "path": "src/XPathQuery.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n\n    /**\n     * Class XPathQuery\n     *\n     * @package TheSeer\\fDOM\n     */\n    class XPathQuery {\n\n        /**\n         * @var string\n         */\n        private $query;\n\n        /**\n         * Key-value Map for bound values\n         *\n         * @var array\n         */\n        private $values = array();\n\n        /**\n         * @param string $query\n         */\n        public function __construct($query) {\n            $this->setQuery($query);\n        }\n\n        /**\n         * Set Query.\n         *\n         * @param string $query\n         */\n        private function setQuery($query) {\n            $this->query = $query;\n            $res = preg_match_all('/(:(\\w*))/', $query, $matches);\n            if ($res > 0) {\n                $this->values = array_fill_keys($matches[2], '');\n            }\n        }\n\n        /**\n         * Returns keys.\n         *\n         * @return array\n         */\n        public function getKeys() {\n            return array_keys($this->values);\n        }\n\n        /**\n         * Bind value to key.\n         *\n         * @param string $key\n         * @param string $value\n         *\n         * @throws XPathQueryException\n         */\n        public function bind($key, $value) {\n            if (!array_key_exists($key, $this->values)) {\n                throw new XPathQueryException(\"'$key' not found in query'\", XPathQueryException::KeyNotFound );\n            }\n            $this->values[$key] = $value;\n        }\n\n        /**\n         * Generate query.\n         *\n         * @param \\DOMNode $ctx\n         * @param array $values\n         *\n         * @return string\n         */\n        public function generate(\\DOMNode $ctx, array $values = NULL) {\n            return $this->buildQuery($this->getXPathObjectFor($ctx), $values);\n        }\n\n        /**\n         * Evaluate Query.\n         *\n         * @param \\DOMNode $ctx\n         * @param array $values\n         * @param bool $registerNodeNS\n         *\n         * @throws fDOMException\n         *\n         * @return mixed\n         */\n        public function evaluate(\\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) {\n            $xp = $this->getXPathObjectFor($ctx);\n            return $xp->evaluate($this->buildQuery($xp, $values), $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Execute Query.\n         *\n         * @param \\DOMNode $ctx\n         * @param array $values\n         * @param bool $registerNodeNS\n         *\n         * @throws fDOMException\n         *\n         * @return mixed\n         */\n        public function query(\\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) {\n            $xp = $this->getXPathObjectFor($ctx);\n            return $xp->evaluate($this->buildQuery($xp, $values), $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Execute Query and return first result.\n         *\n         * @param \\DOMNode $ctx\n         * @param array $values\n         * @param bool $registerNodeNS\n         *\n         * @return \\DOMNode\n         */\n        public function queryOne(\\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) {\n            $xp = $this->getXPathObjectFor($ctx);\n            return $xp->queryOne($this->buildQuery($xp, $values), $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Return xPath for node\n         *\n         * @param \\DOMNode $ctx\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMXPath\n         */\n        private function getXPathObjectFor(\\DOMNode $ctx) {\n            $dom = $ctx instanceof \\DOMDocument ? $ctx : $ctx->ownerDocument;\n            if ($dom instanceOf fDOMDocument) {\n                return $dom->getDOMXPath();\n            }\n            return new fDOMXPath($dom);\n        }\n\n        /**\n         * Build query using values.\n         *\n         * @param fDOMXPath $xp\n         * @param array $values\n         *\n         * @throws XPathQueryException\n         *\n         * @return string\n         */\n        private function buildQuery(fDOMXPath $xp, array $values = NULL) {\n            $backup = $this->values;\n            if (is_array($values) && count($values) > 0) {\n                foreach($values as $k => $v) {\n                    $this->bind($k, $v);\n                }\n            }\n            $query = $xp->prepare($this->query, $this->values);\n            $this->values = $backup;\n            return $query;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/XPathQueryException.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n\n    class XPathQueryException extends \\Exception {\n        const KeyNotFound = 1;\n    }\n\n}\n"
  },
  {
    "path": "src/autoload.php",
    "content": "<?php\n// @codingStandardsIgnoreFile\n// @codeCoverageIgnoreStart\n// this is an autogenerated file - do not edit\nspl_autoload_register(\n    function($class) {\n        static $classes = null;\n        if ($classes === null) {\n            $classes = array(\n                'theseer\\\\fdom\\\\css\\\\dollarequalrule' => '/css/DollarEqualRule.php',\n                'theseer\\\\fdom\\\\css\\\\notrule' => '/css/NotRule.php',\n                'theseer\\\\fdom\\\\css\\\\nthchildrule' => '/css/NthChildRule.php',\n                'theseer\\\\fdom\\\\css\\\\regexrule' => '/css/RegexRule.php',\n                'theseer\\\\fdom\\\\css\\\\ruleinterface' => '/css/RuleInterface.php',\n                'theseer\\\\fdom\\\\css\\\\translator' => '/css/Translator.php',\n                'theseer\\\\fdom\\\\fdomdocument' => '/fDOMDocument.php',\n                'theseer\\\\fdom\\\\fdomdocumentfragment' => '/fDOMDocumentFragment.php',\n                'theseer\\\\fdom\\\\fdomelement' => '/fDOMElement.php',\n                'theseer\\\\fdom\\\\fdomexception' => '/fDOMException.php',\n                'theseer\\\\fdom\\\\fdomnode' => '/fDOMNode.php',\n                'theseer\\\\fdom\\\\fdomxpath' => '/fDOMXPath.php',\n                'theseer\\\\fdom\\\\xpathquery' => '/XPathQuery.php',\n                'theseer\\\\fdom\\\\xpathqueryexception' => '/XPathQueryException.php'\n            );\n        }\n        $cn = strtolower($class);\n        if (isset($classes[$cn])) {\n            require __DIR__ . $classes[$cn];\n        }\n    }\n);\n// @codeCoverageIgnoreEnd\n"
  },
  {
    "path": "src/css/DollarEqualRule.php",
    "content": "<?php\nnamespace TheSeer\\fDOM\\CSS {\n\n    class DollarEqualRule implements RuleInterface {\n\n        /**\n         * @param $selector\n         *\n         * @return string\n         */\n        public function apply($selector) {\n            return preg_replace_callback(\n                '/\\[([a-zA-Z0-9\\_\\-]+)\\$=([^\\]]+)\\]/',\n                array($this, 'callback'),\n                $selector\n            );\n        }\n\n        /**\n         * Build query from matches.\n         *\n         * @param array $matches\n         *\n         * @return string\n         */\n        private function callback(array $matches) {\n            return '[substring(@' . $matches[1] . ',string-length(@' . $matches[1] . ')-' .  (strlen($matches[2]) - 3) . ')=' . $matches[1] . ']';\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/css/NotRule.php",
    "content": "<?php\nnamespace TheSeer\\fDOM\\CSS {\n\n    class NotRule implements RuleInterface {\n\n        /**\n         * @var Translator\n         */\n        private $translator;\n\n        /**\n         * @param Translator $translator\n         */\n        public function __construct(Translator $translator) {\n            $this->translator = $translator;\n        }\n\n        /**\n         * @param $selector\n         *\n         * @return string\n         */\n        public function apply($selector) {\n            return preg_replace_callback(\n                '/([a-zA-Z0-9\\_\\-\\*]+):not\\(([^\\)]*)\\)/',\n                array($this, 'callback'),\n                $selector\n            );\n        }\n\n        /**\n         * @param array $matches\n         *\n         * @return string\n         */\n        private function callback(array $matches) {\n            $subresult = preg_replace(\n                '/^[^\\[]+\\[([^\\]]*)\\].*$/',\n                '$1',\n                $this->translator->translate($matches[2])\n            );\n            return $matches[1] .  '[not(' . $subresult . ')]';\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/css/NthChildRule.php",
    "content": "<?php\nnamespace TheSeer\\fDOM\\CSS {\n\n    class NthChildRule implements RuleInterface {\n\n        /**\n         * @param $selector\n         *\n         * @return string\n         */\n        public function apply($selector) {\n            return preg_replace_callback(\n                '/([a-zA-Z0-9\\_\\-\\*]+):nth-child\\(([^\\)]*)\\)/',\n                array($this, 'callback'),\n                $selector\n            );\n        }\n\n        /**\n         * @param array $matches\n         *\n         * @return string\n         */\n        private function callback(array $matches) {\n            switch($matches[2]){\n                case 'n': {\n                    return $matches[1];\n                }\n                case 'even': {\n                    return '*[position() mod 2=0 and position()>=0]/self::' . $matches[1];\n                }\n                case 'odd': {\n                    return $matches[1] . '[(count(preceding-sibling::*) + 1) mod 2=1]';\n                }\n                default: {\n                    $b = !isset($matches[2]) || empty($matches[2]) ? '0' : $matches[2];\n                    $b = preg_replace('/^([0-9]*)n.*?([0-9]*)$/', '$1+$2', $b);\n                    $b = explode('+', $b);\n                    if (!isset($b[1])) {\n                        $b[1] = '0';\n                    }\n                    return '*[(position()-' . $b[1] . ') mod ' . $b[0] . '=0 and position()>=' . $b[1] . ']/self::' . $matches[1];\n                }\n            }\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/css/RegexRule.php",
    "content": "<?php\nnamespace TheSeer\\fDOM\\CSS {\n\n    class RegexRule implements RuleInterface {\n\n        /**\n         * @var string\n         */\n        private $regex;\n\n        /**\n         * @var string\n         */\n        private $replacement;\n\n        /**\n         * @param string $regex\n         * @param string $replacement\n         */\n        public function __construct($regex, $replacement) {\n            $this->regex = $regex;\n            $this->replacement = $replacement;\n        }\n\n        /**\n         * @param $selector\n         *\n         * @return string\n         */\n        public function apply($selector) {\n            return preg_replace($this->regex, $this->replacement, $selector);\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/css/RuleInterface.php",
    "content": "<?php\nnamespace TheSeer\\fDOM\\CSS {\n\n    interface RuleInterface {\n\n        /**\n         * @param $selector\n         *\n         * @return string\n         */\n        public function apply($selector);\n\n    }\n\n}\n"
  },
  {
    "path": "src/css/Translator.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM\\CSS {\n\n    /**\n     * Class Translator\n     *\n     * The regular expressions used in this class are heavily inspired by and mostly adopted from\n     * the css2xpath.js code by Andrea Giammarchi (http://code.google.com/p/css2xpath/).\n     * The JavaScript version (css2xpath.js) is licensed under the MIT License\n     *\n     */\n    class Translator {\n\n        /**\n         * @var array\n         */\n        private $rules;\n\n        /**\n         * @param string $selector A CSS Selector string\n         *\n         * @return string\n         */\n        public function translate($selector) {\n            foreach($this->getRules() as $rule) {\n                /** @var RuleInterface $rule */\n                $selector = $rule->apply($selector);\n            }\n            return '//' . $selector;\n        }\n\n        /**\n         * @return array\n         */\n        private function getRules() {\n            if ($this->rules != NULL) {\n                return $this->rules;\n            }\n\n            $this->rules = array(\n\n                // prefix|name\n                new RegexRule('/([a-zA-Z0-9\\_\\-\\*]+)\\|([a-zA-Z0-9\\_\\-\\*]+)/', '$1:$2'),\n\n                // add @ for attribs\n                new RegexRule(\"/\\[([^\\]~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]/\", '[@$1$2]'),\n\n                // multiple queries\n                new RegexRule(\"/\\s*,\\s*/\", '|'),\n\n                // , + ~ >\n                new RegexRule(\"/\\s*(\\+|~|>)\\s*/\", '$1'),\n\n                //* ~ + >\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*])~([a-zA-Z0-9\\_\\-\\*])/\", '$1/following-sibling::$2'),\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*])\\+([a-zA-Z0-9\\_\\-\\*])/\", '$1/following-sibling::*[1]/self::$2'),\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*])>([a-zA-Z0-9\\_\\-\\*])/\", '$1/$2'),\n\n                // all unescaped stuff escaped\n                new RegexRule(\"/\\[([^=]+)=([^'|'][^\\]]*)\\]/\", '[$1=\"$2\"]'),\n\n                // all descendant or self to //\n                new RegexRule(\"/(^|[^a-zA-Z0-9\\_\\-\\*])(#|\\.)([a-zA-Z0-9\\_\\-]+)/\", '$1*$2$3'),\n                new RegexRule(\"/([\\>\\+\\|\\~\\,\\s])([a-zA-Z\\*]+)/\", '$1//$2'),\n                new RegexRule(\"/\\s+\\/\\//\", '//'),\n\n                // :first-child\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*]+):first-child/\", '*[1]/self::$1'),\n\n                // :last-child\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*]+):last-child/\", '$1[not(following-sibling::*)]'),\n\n                // :only-child\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*]+):only-child/\", '*[last()=1]/self::$1'),\n\n                // :empty\n                new RegexRule(\"/([a-zA-Z0-9\\_\\-\\*]+):empty/\", '$1[not(*) and not(normalize-space())]'),\n\n                // :not\n                new NotRule($this),\n\n                // :nth-child\n                new NthChildRule(),\n\n                // :contains(selectors)\n                new RegexRule('/:contains\\(([^\\)]*)\\)/', '[contains(string(.),\"$1\")]'),\n\n                // |= attrib\n                new RegexRule(\"/\\[([a-zA-Z0-9\\_\\-]+)\\|=([^\\]]+)\\]/\", '[@$1=$2 or starts-with(@$1,concat($2,\"-\"))]'),\n\n                // *= attrib\n                new RegexRule(\"/\\[([a-zA-Z0-9\\_\\-]+)\\*=([^\\]]+)\\]/\", '[contains(@$1,$2)]'),\n\n                // ~= attrib\n                new RegexRule(\"/\\[([a-zA-Z0-9\\_\\-]+)~=([^\\]]+)\\]/\", '[contains(concat(\" \",normalize-space(@$1),\" \"),concat(\" \",$2,\" \"))]'),\n\n                // ^= attrib\n                new RegexRule(\"/\\[([a-zA-Z0-9\\_\\-]+)\\^=([^\\]]+)\\]/\", '[starts-with(@$1,$2)]'),\n\n                // $= attrib\n                new DollarEqualRule(),\n\n                // != attrib\n                new RegexRule(\"/\\[([a-zA-Z0-9\\_\\-]+)\\!=([^\\]]+)\\]/\", '[not(@$1) or @$1!=$2]'),\n\n                // ids and classes\n                new RegexRule(\"/#([a-zA-Z0-9\\_\\-]+)/\", '[@id=\"$1\"]'),\n                new RegexRule(\"/\\.([a-zA-Z0-9\\_\\-]+)/\", '[contains(concat(\" \",normalize-space(@class),\" \"),\" $1 \")]'),\n\n                // normalize multiple filters\n                new RegexRule(\"/\\]\\[([^\\]]+)/\", ' and ($1)')\n\n            );\n            return $this->rules;\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/fDOMDocument.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n    use TheSeer\\fDOM\\CSS\\Translator;\n\n    /**\n     * fDOMDocument extension to PHP's DOMDocument.\n     * This class adds various convenience methods to simplify APIs\n     * It is set to final since further extending it would even more\n     * break the Object structure after use of registerNodeClass.\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @access    public\n     * @property  fDOMDocument $ownerDocument\n     *\n     */\n    class fDOMDocument extends \\DOMDocument {\n\n        /**\n         * XPath Object instance\n         *\n         * @var fDOMXPath\n         */\n        private $xp = NULL;\n\n        /**\n         * List of registered prefixes and their namespace uri\n         * @var array\n         */\n        private $prefixes = array();\n\n        /**\n         * Extended DOMDocument constructor\n         *\n         * @param string $version       XML Version, should be 1.0\n         * @param string $encoding      Encoding, defaults to utf-8\n         * @param array  $streamOptions optional stream options array\n         *\n         * @return fDOMDocument\n         */\n        public function __construct($version = '1.0', $encoding = 'utf-8', $streamOptions = NULL) {\n            if (!is_null($streamOptions)) {\n                $this->setStreamContext($streamOptions);\n            }\n\n            libxml_use_internal_errors(TRUE);\n            $rc = parent::__construct($version, $encoding);\n\n            $this->registerNodeClasses();\n\n            return $rc;\n        }\n\n        /**\n         * Reset XPath object so the clone gets a new instance when needed\n         */\n        public function __clone() {\n            $this->registerNodeClasses();\n            $this->xp = new fDOMXPath($this);\n            foreach($this->prefixes as $prefix => $uri) {\n                $this->xp->registerNamespace($prefix, $uri);\n            }\n        }\n\n        /**\n         * @return string\n         */\n        public function __toString() {\n            return $this->C14N();\n        }\n\n        /**\n         * Set Stream context options\n         *\n         * @param array $options Stream context options\n         *\n         * @return boolean true on success, false on failure\n         */\n        public function setStreamContext(array $options) {\n            if (!count($options)) {\n                return FALSE;\n            }\n            $context = stream_context_create($options);\n            libxml_set_streams_context($context);\n            return TRUE;\n        }\n\n        /**\n         * Wrapper to DOMDocument load with exception handling\n         * Returns true on success to satisfy the compatibilty of the original DOM Api\n         *\n         * @param string  $fname   File to load\n         * @param int|null $options LibXML Flags to pass\n         *\n         * @throws fDOMException\n         *\n         * @return bool|mixed\n         */\n        public function load($fname, $options = LIBXML_NONET) {\n            if ($fname === '') {\n                throw new fDOMException('empty filename is not allowed', fDOMException::ParseError);\n            }\n            $this->xp = NULL;\n            $tmp = parent :: load($fname, $options);\n            if (!$tmp || libxml_get_last_error()) {\n                throw new fDOMException(\"loading file '$fname' failed.\", fDOMException::LoadError);\n            }\n            $this->registerNodeClasses();\n            return TRUE;\n        }\n\n        /**\n         * Wrapper to DOMDocument loadXML with exception handling\n         * Returns true on success to satisfy the compatibilty of the original DOM Api\n         *\n         * @param string  $source  XML source code\n         * @param integer $options LibXML option flags\n         *\n         * @throws fDOMException\n         *\n         * @return boolean\n         */\n        public function loadXML($source, $options = LIBXML_NONET) {\n            if ($source === '') {\n                throw new fDOMException('empty string not allowed', fDOMException::ParseError);\n            }\n            $this->xp = NULL;\n            $tmp = parent :: loadXML($source, $options);\n            if (!$tmp || libxml_get_last_error()) {\n                throw new fDOMException('parsing string failed:' . (libxml_get_last_error())->message, fDOMException::ParseError);\n            }\n            $this->registerNodeClasses();\n            return TRUE;\n        }\n\n        /**\n         * Wrapper to DOMDocument loadHTMLFile with exception handling.\n         * Returns true on success to satisfy the compatibilty of the original DOM Api\n         *\n         * @param string  $fname html file to load\n         * @param integer $options Options bitmask (@see DOMDocument::loadHTMLFile)\n         *\n         * @throws fDOMException\n         *\n         * @return boolean\n         */\n        public function loadHTMLFile($fname, $options = NULL) {\n            if ($fname === '') {\n                throw new fDOMException('empty filename is not allowed', fDOMException::ParseError);\n            }\n            $this->xp = NULL;\n            if (version_compare(PHP_VERSION, '5.4.0', '<')) {\n                if ($options !== NULL) {\n                    throw new fDOMException('Passing options requires PHP 5.4.0+', fDOMException::LoadError);\n                }\n                $tmp = parent :: loadHTMLFile($fname);\n            } else {\n                $tmp = parent :: loadHTMLFile($fname, $options);\n            }\n            if (!$tmp || libxml_get_last_error()) {\n                throw new fDOMException(\"loading html file '$fname' failed\", fDOMException::LoadError);\n            }\n            $this->registerNodeClasses();\n            return TRUE;\n        }\n\n        /**\n         * Wrapper to DOMDocument loadHTML with exception handling\n         * Returns true on success to satisfy the compatibilty of the original DOM Api\n         *\n         * @param string  $source html source code\n         * @param integer $options Options bitmask (@see DOMDocument::loadHTML)\n         *\n         * @throws fDOMException\n         *\n         * @return boolean\n         */\n        public function loadHTML($source, $options = NULL) {\n            if ($source === '') {\n                throw new fDOMException('empty string not allowed', fDOMException::ParseError);\n            }\n            $this->xp = NULL;\n            if (version_compare(PHP_VERSION, '5.4.0', '<')) {\n                if ($options !== NULL) {\n                    throw new fDOMException('Passing options requires PHP 5.4.0+', fDOMException::LoadError);\n                }\n                $tmp = parent :: loadHTML($source);\n            } else {\n                $tmp = parent :: loadHTML($source, $options);\n            }\n            if (!$tmp || libxml_get_last_error()) {\n                throw new fDOMException('parsing html string failed', fDOMException::ParseError);\n            }\n            $this->registerNodeClasses();\n            return TRUE;\n        }\n\n        /**\n         * Wrapper to DOMDocument::save with exception handling\n         *\n         * @param string  $filename filename to save to\n         * @param integer $options Options bitmask (@see DOMDocument::save)\n         *\n         * @throws fDOMException\n         *\n         * @return integer bytes saved\n         */\n        #[\\ReturnTypeWillChange]\n        public function save($filename, $options = NULL) {\n            $tmp = parent::save($filename, $options);\n            if (!$tmp) {\n                throw new fDOMException(\"Saving XML to file '$filename' failed\", fDOMException::SaveError);\n            }\n            return $tmp;\n        }\n\n        /**\n         * Wrapper to DOMDocument::saveHTML with exception handling\n         *\n         * @param \\DOMNode|null $node Context DOMNode (optional)\n         *\n         * @throws fDOMException\n         *\n         * @return string html content\n         */\n        #[\\ReturnTypeWillChange]\n        public function saveHTML(\\DOMNode $node = NULL) {\n            if (version_compare(PHP_VERSION, '5.3.6', '<') && $node !== NULL) {\n                throw new fDOMException('Passing a context node requires PHP 5.3.6+', fDOMException::SaveError);\n            }\n            $tmp = parent::saveHTML($node);\n            if (!$tmp) {\n                throw new fDOMException('Serializing to HTML failed', fDOMException::SaveError);\n            }\n            return $tmp;\n        }\n\n        /**\n         * Wrapper to DOMDocument::saveHTMLfile with exception handling\n         *\n         * @param string $filename filename to save to\n         * @param integer $options Options bitmask (@see DOMDocument::saveHTMLFile)\n         *\n         * @throws fDOMException\n         *\n         * @return integer bytes saved\n         */\n        #[\\ReturnTypeWillChange]\n        public function saveHTMLFile($filename, $options = NULL) {\n            $tmp = parent::saveHTMLFile($filename, $options);\n            if (!$tmp) {\n                throw new fDOMException(\"Saving HTML to file '$filename' failed\", fDOMException::SaveError);\n            }\n            return $tmp;\n        }\n\n        /**\n         * Wrapper to DOMDocument::saveXML with exception handling\n         *\n         * @param \\DOMNode $node    node to start serializing at\n         * @param integer  $options options flags as bitmask\n         *\n         * @throws fDOMException\n         *\n         * @return string serialized XML\n         */\n        #[\\ReturnTypeWillChange]\n        public function saveXML(\\DOMNode $node = NULL, $options = NULL) {\n            try {\n                if ($options !== null) {\n                    $tmp = parent::saveXML($node, $options);\n                } else {\n                    $tmp = parent::saveXML($node);\n                }\n\n                if (!$tmp) {\n                    throw new fDOMException('Serializing to XML failed', fDOMException::SaveError);\n                }\n                return $tmp;\n            } catch (\\Exception $e) {\n                if (!$e instanceof fDOMException) {\n                    throw new fDOMException($e->getMessage(), fDOMException::SaveError, $e);\n                }\n                throw $e;\n            }\n        }\n\n        /**\n         * get Instance of DOMXPath Object for current DOM\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMXPath\n         */\n        public function getDOMXPath() {\n            if (is_null($this->xp)) {\n                $this->xp = new fDOMXPath($this);\n            }\n            if (!$this->xp) {\n                throw new fDOMException('creating DOMXPath object failed.', fDOMException::NoDOMXPath);\n            }\n            return $this->xp;\n        }\n\n        /**\n         * Convert a given DOMNodeList into a DOMFragment\n         *\n         * @param \\DOMNodeList $list The Nodelist to process\n         * @param boolean     $move Signale if nodes are to be moved into fragment or not\n         *\n         * @return fDOMDocumentFragment\n         */\n        public function nodeList2Fragment(\\DOMNodeList $list, $move=FALSE) {\n            $frag = $this->createDocumentFragment();\n            /** @var fDOMNode $node */\n            foreach($list as $node) {\n                $frag->appendChild($move ? $node : $node->cloneNode(TRUE));\n            }\n            return $this->ensureIntance($frag);\n        }\n\n        /**\n         * Perform an xpath query\n         *\n         * @param String   $q   query string containing xpath\n         * @param \\DOMNode|null $ctx (optional) Context DOMNode\n         * @param boolean  $registerNodeNS  Register flag pass through\n         *\n         * @return \\DOMNodeList\n         */\n        public function query($q, \\DOMNode $ctx = NULL, $registerNodeNS = TRUE) {\n            if (is_null($this->xp)) {\n                $this->getDOMXPath();\n            }\n            return $this->xp->evaluate($q, $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Perform an xpath query and return only the 1st match\n         *\n         * @param String   $q   query string containing xpath\n         * @param \\DOMNode  $ctx (optional) Context DOMNode\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return fDOMNode\n         */\n        public function queryOne($q, \\DOMNode $ctx = NULL, $registerNodeNS = TRUE) {\n            if (is_null($this->xp)) {\n                $this->getDOMXPath();\n            }\n            return $this->xp->queryOne($q, $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Forwarder to fDOMXPath's prepare method allowing for easy and secure\n         * placeholder replacement comparable to sql's prepared statements\n         * .\n         * @param string $xpath    String containing xpath with :placeholder markup\n         * @param array  $valueMap array containing keys (:placeholder) and value pairs to be quoted\n         *\n         * @return string\n         */\n        public function prepareQuery($xpath, array $valueMap) {\n            if (is_null($this->xp)) {\n                $this->getDOMXPath();\n            }\n            return $this->xp->prepare($xpath, $valueMap);\n        }\n\n        /**\n         * Use a CSS Level 3 Selector string to query select nodes\n         *\n         * @param string   $selector A CSS Level 3 Selector string\n         * @param \\DOMNode $ctx\n         * @param bool     $registerNodeNS\n         *\n         * @return \\DOMNodeList\n         */\n        public function select($selector, \\DOMNode $ctx = NULL, $registerNodeNS = TRUE) {\n            $translator = new Translator();\n            $xpath = $translator->translate($selector);\n            if ($ctx !== NULL) {\n                $xpath = '.' . $xpath;\n            }\n            return $this->query($xpath, $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Forward to DOMXPath->registerNamespace()\n         *\n         * @param string $prefix The prefix to use\n         * @param string $uri    The uri to assign to this prefix\n         *\n         * @throws fDOMException\n         *\n         * @return void\n         */\n        public function registerNamespace($prefix, $uri) {\n            if (is_null($this->xp)) {\n                $this->getDOMXPath();\n            }\n            if (!$this->xp->registerNamespace($prefix, $uri)) {\n                throw new fDOMException(\"Registering namespace '$uri' with prefix '$prefix' failed.\", fDOMException::RegistrationFailed);\n            }\n            $this->prefixes[$prefix] = $uri;\n        }\n\n        /**\n         * Forward to DOMXPath->registerPHPFunctions()\n         *\n         * @param mixed $restrict array of function names or string with functionname to restrict callabilty to\n         *\n         * @throws fDOMException\n         *\n         * @return void\n         */\n        public function registerPHPFunctions($restrict = NULL) {\n            if (is_null($this->xp)) {\n                $this->getDOMXPath();\n            }\n            $this->xp->registerPHPFunctions($restrict);\n            if (libxml_get_last_error()) {\n                throw new fDOMException(\"Registering php functions failed.\", fDOMException::RegistrationFailed);\n            }\n        }\n\n        /**\n         * Create a new element in namespace defined by given prefix\n         *\n         * @param string $prefix   Namespace prefix for node to create\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         * @param bool $asTextNode Create content as textNode rather then setting nodeValue\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function createElementPrefix($prefix, $name, $content = NULL, $asTextNode = FALSE) {\n            if (!isset($this->prefixes[$prefix])) {\n                throw new fDOMException(\"'$prefix' not bound\", fDOMException::UnboundPrefix);\n            }\n            return $this->createElementNS($this->prefixes[$prefix], $prefix.':'.$name, $content, $asTextNode);\n        }\n\n        /**\n         * Create a new fDOMElement and return it, optionally set content\n         *\n         * @param string $name Name of node to create\n         * @param null $content Content to set (optional)\n         * @param bool $asTextnode Create content as textNode rather then setting nodeValue\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function createElement($name, $content = NULL, $asTextnode = FALSE) {\n            try {\n                $node = parent::createElement($name);\n                if (!$node) {\n                    throw new fDOMException(\"Creating element with name '$name' failed\", fDOMException::NameInvalid);\n                }\n                if ($content !== NULL) {\n                    if ($asTextnode) {\n                        $node->appendChild($this->createTextnode($content));\n                    } else {\n                        $node->nodeValue = $content;\n                    }\n                    if (libxml_get_errors()) {\n                        throw new fDOMException(\"Setting content value failed\", fDOMException::SetFailedError);\n                    }\n                }\n                return $this->ensureIntance($node);\n            } catch (\\DOMException $e) {\n                throw new fDOMException(\"Creating elemnt with name '$name' failed\", 0, $e);\n            }\n\n        }\n\n        /**\n         * Create a new fDOMElement within given namespace and return it\n         *\n         * @param string $namespace Namespace URI for node to create\n         * @param string $name Name of node to create\n         * @param string $content Content to set (optional)\n         * @param bool $asTextNode Create content as textNode rather then setting nodeValue\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMElement\n         */\n        public function createElementNS($namespace, $name, $content = NULL, $asTextNode = FALSE) {\n            $node = parent::createElementNS($namespace, $name);\n            if (!$node) {\n                throw new fDOMException(\"Creating element with name '$name' failed\", fDOMException::NameInvalid);\n            }\n            if ($content !== NULL) {\n                if ($asTextNode) {\n                    $node->appendChild($this->createTextnode($content));\n                } else {\n                    $node->nodeValue = $content;\n                }\n                if (libxml_get_errors()) {\n                    throw new fDOMException(\"Setting content value failed\", fDOMException::SetFailedError);\n                }\n            }\n            return $this->ensureIntance($node);\n        }\n\n        /**\n         * @return fDOMDocumentFragment\n         *\n         */\n        #[\\ReturnTypeWillChange]\n        public function createDocumentFragment() {\n            return $this->ensureIntance(parent::createDocumentFragment());\n        }\n\n        /**\n         * Check if the given node is in the same document\n         *\n         * @param \\DOMNode $node Node to compare with\n         *\n         * @return boolean true on match, false if they differ\n         *\n         */\n        public function inSameDocument(\\DOMNode $node) {\n            if ($node instanceof \\DOMDocument) {\n                return $this->isSameNode($node);\n            }\n            return $this->isSameNode($node->ownerDocument);\n        }\n\n        /**\n         * Create a new element and append it as documentElement\n         *\n         * @param string $name Name of not element to create\n         * @param string $content Optional content to be set\n         * @param bool $asTextNode\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElement($name, $content = NULL, $asTextNode = FALSE) {\n            return $this->appendChild(\n                $this->createElement($name, $content, $asTextNode)\n            );\n        }\n\n        /**\n         * Create a new element in given namespace and append it as documentElement\n         *\n         * @param string $ns Namespace of node to create\n         * @param string $name Name of not element to create\n         * @param string $content Optional content to be set\n         * @param bool $asTextNode\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElementNS($ns, $name, $content = NULL, $asTextNode = FALSE) {\n            return $this->appendChild(\n                $this->createElementNS($ns, $name, $content, $asTextNode)\n            );\n        }\n\n        /**\n         * This is a workaround for hhvm's broken registerNodeClass handling\n         * (https://github.com/facebook/hhvm/issues/1848)\n         *\n         * @param \\DOMNode $node\n         *\n         * @return \\DOMNode\n         */\n        private function ensureIntance(\\DOMNode $node) {\n            if ($node instanceof fDOMNode || $node instanceof fDOMElement || $node instanceof fDOMDocumentFragment) {\n                return $node;\n            }\n            return $this->importNode($node, TRUE);\n        }\n\n        /**\n         * Register replacements\n         *\n         * Called from constructor and, as a workaround for (https://github.com/facebook/hhvm/issues/5412),\n         * after load(), loadXML(), loadHTML() and loadHTMLFile()\n         */\n        private function registerNodeClasses() {\n            $this->registerNodeClass('DOMDocument', get_called_class());\n            $this->registerNodeClass('DOMNode', 'TheSeer\\fDOM\\fDOMNode');\n            $this->registerNodeClass('DOMElement', 'TheSeer\\fDOM\\fDOMElement');\n            $this->registerNodeClass('DOMDocumentFragment', 'TheSeer\\fDOM\\fDOMDocumentFragment');\n        }\n\n    } // fDOMDocument\n\n}\n"
  },
  {
    "path": "src/fDOMDocumentFragment.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n\n    /**\n     * fDOMDocumentFragment\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @access    public\n     * @property  fDOMDocument $ownerDocument\n     *\n     */\n    class fDOMDocumentFragment extends \\DOMDocumentFragment {\n\n        /**\n         * @return string\n         */\n        public function __toString() {\n            return $this->ownerDocument->saveXML($this);\n        }\n\n        /**\n         * Wrapper to standard method with exception support\n         *\n         * @param string $str Data string to parse and append\n         *\n         * @throws fDOMException\n         *\n         * @return bool true on success\n         */\n        #[\\ReturnTypeWillChange]\n        public function appendXML($str) {\n            if (!parent::appendXML($str)) {\n                throw new fDOMException('Appending xml string failed', fDOMException::ParseError);\n            }\n            return true;\n        }\n\n        /**\n         * Create a new element and append it\n         *\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElement($name, $content = null) {\n            $node = $this->ownerDocument->createElement($name, $content);\n            $this->appendChild($node);\n            return $node;\n        }\n\n        /**\n         * Create a new element in given namespace and append it\n         *\n         * @param string $ns       Namespace of node to create\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElementNS($ns, $name, $content = null) {\n            $node = $this->ownerDocument->createElementNS($ns, $name, $content);\n            $this->appendChild($node);\n            return $node;\n        }\n\n        /**\n         * Create a new element in given namespace and append it\n         *\n         * @param string $prefix   Namespace prefix for node to create\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         * @param bool $asTextnode Create content as textNode rather then setting nodeValue\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElementPrefix($prefix, $name, $content = null, $asTextnode = FALSE) {\n            $node = $this->ownerDocument->createElementPrefix($prefix, $name, $content, $asTextnode);\n            $this->appendChild($node);\n            return $node;\n        }\n\n        /**\n         * Create a new text node and append it\n         *\n         * @param string $content Text content to be added\n         *\n         * @return \\DOMText\n         */\n        public function appendTextNode($content) {\n            $text = $this->ownerDocument->createTextNode($content);\n            $this->appendChild($text);\n            return $text;\n        }\n\n        /**\n         * Check if the given node is in the same document\n         *\n         * @param \\DOMNode $node Node to compare with\n         *\n         * @return boolean true on match, false if they differ\n         *\n         */\n        public function inSameDocument(\\DOMNode $node) {\n            return $this->ownerDocument->inSameDocument($node);\n        }\n\n\n        /**\n         * Forward to fDomDocument->query()\n         *\n         * @param string   $q               XPath to use\n         * @param \\DOMNode $ctx             \\DOMNode to overwrite context\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return \\DomNodeList\n         */\n        public function query($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->query($q, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n        /**\n         * Forward to fDomDocument->queryOne()\n         *\n         * @param string   $q               XPath to use\n         * @param \\DOMNode $ctx             (optional) \\DOMNode to overwrite context\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return mixed\n         */\n        public function queryOne($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->queryOne($q, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n        /**\n         * Forward to fDomDocument->select()\n         *\n         * @param string   $selector A CSS Level 3 Selector string\n         * @param \\DOMNode $ctx\n         * @param bool     $registerNodeNS\n         *\n         * @return \\DOMNodeList\n         */\n        public function select($selector, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->select($selector, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n    } // fDOMDocumentFragment\n\n}\n"
  },
  {
    "path": "src/fDOMElement.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n\n    /**\n     * fDomElement\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @access    public\n     * @property  fDOMDocument $ownerDocument\n     *\n     */\n    class fDOMElement extends \\DOMElement {\n\n        /**\n         * @return string\n         */\n        public function __toString() {\n            return $this->C14N();\n        }\n\n        /**\n         * Forward to fDomDocument->query()\n         *\n         * @param string   $q               XPath to use\n         * @param \\DOMNode $ctx             \\DOMNode to overwrite context\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return \\DomNodeList\n         */\n        public function query($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->query($q, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n        /**\n         * Forward to fDomDocument->queryOne()\n         *\n         * @param string   $q               XPath to use\n         * @param \\DOMNode $ctx             (optional) \\DOMNode to overwrite context\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return mixed\n         */\n        public function queryOne($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->queryOne($q, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n        /**\n         * Forward to fDomDocument->select()\n         *\n         * @param string   $selector A CSS Level 3 Selector string\n         * @param \\DOMNode $ctx\n         * @param bool     $registerNodeNS\n         *\n         * @return \\DOMNodeList\n         */\n\n        public function select($selector, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->select($selector, $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Parse and append XML String to node\n         *\n         * @param String $str string to process\n         *\n         * @return fDomDocumentFragment Reference to the created Fragment\n         */\n        public function appendXML($str) {\n            $frag = $this->ownerDocument->createDocumentFragment();\n            $frag->appendXML($str);\n            $this->appendChild($frag);\n            return $frag;\n        }\n\n        /**\n         * Create a new element and append it\n         *\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         * @param bool $asTextnode Create content as textNode rather then setting nodeValue\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElement($name, $content = null, $asTextnode = FALSE) {\n            $node = $this->ownerDocument->createElement($name, $content, $asTextnode);\n            $this->appendChild($node);\n            return $node;\n        }\n\n        /**\n         * Create a new element in given namespace and append it\n         *\n         * @param string $ns       Namespace of node to create\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         * @param bool $asTextnode Create content as textNode rather then setting nodeValue\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElementNS($ns, $name, $content = null, $asTextnode = FALSE) {\n            $node = $this->ownerDocument->createElementNS($ns, $name, $content, $asTextnode);\n            $this->appendChild($node);\n            return $node;\n        }\n\n        /**\n         * Create a new element in given namespace and append it\n         *\n         * @param string $prefix   Namespace prefix for node to create\n         * @param string $name     Name of not element to create\n         * @param string $content  Optional content to be set\n         * @param bool $asTextnode Create content as textNode rather then setting nodeValue\n         *\n         * @return fDOMElement Reference to created fDOMElement\n         */\n        public function appendElementPrefix($prefix, $name, $content = null, $asTextnode = FALSE) {\n            $node = $this->ownerDocument->createElementPrefix($prefix, $name, $content, $asTextnode);\n            $this->appendChild($node);\n            return $node;\n        }\n\n        /**\n         * Create a new text node and append it\n         *\n         * @param string $content Text content to be added\n         *\n         * @return \\DOMText\n         */\n        public function appendTextNode($content) {\n            $text = $this->ownerDocument->createTextNode($content);\n            $this->appendChild($text);\n            return $text;\n        }\n\n        /**\n         * Create a new fDOMElement\n         *\n         * @see fDOMDocument::createElement\n         *\n         * @param string $name\n         * @param string $content\n         * @param bool $asTextnode\n         *\n         * @return fDOMElement\n         */\n        public function createElement($name, $content = NULL, $asTextnode = FALSE) {\n            return $this->ownerDocument->createElement($name, $content, $asTextnode);\n        }\n\n        /**\n         * Create a new fDOMElement in namespace defined by prefix\n         *\n         * @see fDOMDocument::createElementPrefix\n         *\n         * @param string $prefix\n         * @param string $name\n         * @param string $content\n         * @param bool $asTextNode\n         *\n         * @return fDOMElement\n         */\n        public function createElementPrefix($prefix, $name, $content = NULL, $asTextNode = FALSE) {\n            return $this->ownerDocument->createElementPrefix($prefix, $name, $content, $asTextNode);\n        }\n\n        /**\n         * Create a new fDOMElement within given namespace and return it\n         *\n         * @param string $namespace Namespace URI for node to create\n         * @param string $name Name of node to create\n         * @param null $content Content to set (optional)\n         * @param bool $asTextNode Create content as textNode rather then setting nodeValue\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMElement\n         */\n        public function createElementNS($namespace, $name, $content = NULL, $asTextNode = FALSE) {\n            return $this->ownerDocument->createElementNS($namespace, $name, $content, $asTextNode);\n        }\n\n        /**\n         * Wrapper to DomElement->getAttribute with default value option\n         *\n         * Note: A set but emptry attribute does NOT trigger use of the default\n         *\n         * @param string $attr    Attribute to access\n         * @param string $default Default value to use if the attribute is not set\n         *\n         * @return string\n         */\n        #[\\ReturnTypeWillChange]\n        public function getAttribute($attr, $default='') {\n            return $this->hasAttribute($attr) ? parent::getAttribute($attr) : $default;\n        }\n\n        /**\n         * Wrapper to DomElement->getAttributeNS with default value option\n         *\n         * Note: A set but empty attribute does NOT trigger use of the default\n         *\n         * @param string $ns      Namespace of attribute\n         * @param string $attr    Attribute to access\n         * @param string $default Default value to use if the attribute is not set\n         *\n         * @return string\n         */\n        #[\\ReturnTypeWillChange]\n        public function getAttributeNS($ns, $attr, $default='') {\n            return $this->hasAttributeNS($ns, $attr) ? parent::getAttributeNS($ns, $attr) : $default;\n        }\n\n        /**\n         * Wrapper to DOMElement::setAttribute with additional entities support\n         *\n         * @param string  $attr          Attribute name to set\n         * @param string  $value         Value to set attribute to\n         * @param bool $keepEntities Flag to signale if entities should be kept\n         *\n         * @throws fDOMException\n         *\n         * @return \\DOMAttr\n         *\n         * @see DOMElement::setAttribute()\n         */\n        #[\\ReturnTypeWillChange]\n        public function setAttribute($attr, $value, $keepEntities=false) {\n            if ($keepEntities === true) {\n                $attrNode = $this->ownerDocument->createAttribute($attr);\n                if (!$attrNode) {\n                   throw new fDOMException(\"Setting attribute '$attr' failed.\", fDOMException::SetFailedError);\n                }\n                $attrNode->value = $value;\n                $this->appendChild($attrNode);\n                return $attrNode;\n            }\n            return parent::setAttribute($attr, $value);\n        }\n\n        /**\n         * Wrapper to namespace aware DOMElement::setAttributeNS with additional entities support\n         *\n         * @param string  $ns            namespace attribute should be in\n         * @param string  $attr          Attribute name to set\n         * @param string  $value         Value to set attribute to\n         * @param bool    $keepEntities  Flag to signale if entities should be kept\n         *\n         * @throws fDOMException\n         *\n         * @return \\DOMAttr|null\n         * @see DOMElement::setAttribute()\n         */\n        #[\\ReturnTypeWillChange]\n        public function setAttributeNS($ns, $attr, $value, $keepEntities=false) {\n            if ($keepEntities === true) {\n                $attrNode = $this->ownerDocument->createAttributeNS($ns, $attr);\n                if (!$attrNode) {\n                   throw new fDOMException(\"Setting attribute '$attr' failed.\", fDOMException::SetFailedError);\n                }\n                $attrNode->value = $value;\n                $this->appendChild($attrNode);\n                return $attrNode;\n            }\n            return parent::setAttributeNS($ns, $attr, $value);\n        }\n\n        /**\n         * Helper to add multiple attributes to an element\n         *\n         * @param array $attr Attributes to add as key-value pair\n         * @param bool $keepEntities Flag wether to keep entities\n         *\n         * @return array List with references to created DOMAttr\n         */\n        public function setAttributes(array $attr, $keepEntities=false) {\n            $attList = array();\n            foreach($attr as $name => $value) {\n               $attList[] = $this->setAttribute($name, $value, $keepEntities);\n            }\n            return $attList;\n        }\n\n        /**\n         * Helper to add multiple attributes with the given namespace and prefix\n         *\n         * @param string $ns       Namespace of attribute\n         * @param string $prefix   Namespace prefix for attribute to create\n         * @param array  $attr     Attributes to add\n         * @param bool $keepEntities Flag wether to keep entities\n         *\n         * @return void\n         */\n        public function setAttributesNS($ns, $prefix, array $attr, $keepEntities=false) {\n           foreach($attr as $name => $value) {\n              $this->setAttributeNS($ns, $prefix.':'.$name, $value, $keepEntities);\n           }\n        }\n\n        /**\n         * Helper method to get children by name\n         *\n         * @param string $tagName tagname to search for\n         *\n         * @return \\DOMNodeList\n         */\n        public function getChildrenByTagName($tagName) {\n            return $this->query(\"*[local-name()='$tagName']\");\n        }\n\n        /**\n         * Helper method to get children by name and namespace\n         *\n         * @param string $ns      namespace nodes have to be in\n         * @param string $tagName tagname to search for\n         *\n         * @return \\DOMNodeList\n         */\n        public function getChildrenByTagNameNS($ns, $tagName) {\n            return $this->query(\"*[local-name()='$tagName' and namespace-uri()='$ns']\");\n        }\n\n        /**\n         * Check if the given node is in the same document\n         *\n         * @param \\DomNode $node Node to compare with\n         *\n         * @return boolean true on match, false if they differ\n         *\n         */\n        public function inSameDocument(\\DomNode $node) {\n            return $this->ownerDocument->inSameDocument($node);\n        }\n\n        /**\n         * Wrapper to DomDocument::saveXML() with current node as context\n         *\n         * @return string\n         */\n        public function saveXML() {\n            return $this->ownerDocument->saveXML($this);\n        }\n\n        /**\n         * Wrapper to DomDocument::saveHTML() with current node as context\n         *\n         * @return string\n         */\n        public function saveHTML() {\n            return $this->ownerDocument->saveHTML($this);\n        }\n\n    } // fDOMElement\n\n}\n"
  },
  {
    "path": "src/fDOMException.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package    fDOM\n * @author     Arne Blankerts <arne@blankerts.de>\n * @copyright  Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license    BSD License\n */\n\nnamespace TheSeer\\fDOM {\n\n    /**\n     * fDOMException\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @access    public\n     *\n     */\n    class fDOMException extends \\Exception {\n\n        const LoadError          = 1;\n        const ParseError         = 2;\n        const SaveError          = 3;\n        const QueryError         = 4;\n        const RegistrationFailed = 5;\n        const NoDOMXPath         = 6;\n        const UnboundPrefix      = 7;\n        const SetFailedError     = 8;\n        const NameInvalid        = 9;\n\n        /**\n         * List of libxml error objects\n         *\n         * @var array\n         */\n        private $errorList;\n\n\n        /**\n         * Full Error message\n         *\n         * @var string\n         */\n        private $fullMessage = null;\n\n\n        /**\n         * Short Error Message\n         *\n         * @var string\n         */\n        private $shortMessage = null;\n\n\n        private static $fullMesageMode = true;\n\n        /**\n         * Constructor\n         *\n         * @param string  $message Exception message\n         * @param integer $code    Exception code\n         * @param \\Exception $chain optional chained exception\n         *\n         */\n        public function __construct($message, $code = 0, \\Exception $chain = NULL) {\n            $this->shortMessage = $message;\n            $this->errorList = libxml_get_errors();\n            libxml_clear_errors();\n            parent :: __construct($message, $code, $chain);\n\n            $this->fullMessage = $message.\"\\n\\n\";\n\n            foreach ($this->errorList as $error) {\n                // hack, skip \"attempt to load external pseudo error\"\n                if ($error->code=='1543') {\n                    continue;\n                }\n\n                if (empty($error->file)) {\n                    $this->fullMessage .= '[XML-STRING] ';\n                } else {\n                    $this->fullMessage .= '['.$error->file.'] ';\n                }\n\n                $this->fullMessage .= '[Line: '.$error->line.' - Column: '.$error->column.'] ';\n\n                switch ($error->level) {\n                    case LIBXML_ERR_WARNING:\n                        $this->fullMessage .= \"Warning $error->code: \";\n                        break;\n                    case LIBXML_ERR_ERROR:\n                        $this->fullMessage .= \"Error $error->code: \";\n                        break;\n                    case LIBXML_ERR_FATAL:\n                        $this->fullMessage .= \"Fatal Error $error->code: \";\n                        break;\n                }\n\n                $this->fullMessage .= str_replace(\"\\n\", '', $error->message).\"\\n\";\n\n                if (self::$fullMesageMode) {\n                    $this->message = $this->fullMessage;\n                }\n\n            }\n        }\n\n        /**\n         * Accessor to fullMessage\n         *\n         * @return string\n         */\n        public function getFullMessage() {\n            return $this->fullMessage;\n        }\n\n        /**\n         * Access to shortMessage\n         *\n         * @return string\n         */\n        public function getShortMessage() {\n            return $this->shortMessage;\n        }\n\n        /**\n         * Accessor to errorList objets\n         *\n         * @return array\n         */\n        public function getErrorList() {\n            return $this->errorList;\n        }\n\n        /**\n         * Toggle wehter getMessage() should return full or only exception message\n         *\n         * @param boolean $full Flag to enable or disable full message output\n         *\n         * @return void\n         */\n        public function toggleFullMessage($full = true) {\n            $this->message = $full ? $this->fullMessage : $this->shortMessage;\n        }\n\n        /**\n         * Magic method for string context\n         *\n         * @return string\n         */\n        public function __toString() {\n            return $this->fullMessage;\n        }\n\n    } // fDOMException\n\n}\n"
  },
  {
    "path": "src/fDOMNode.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n\n    /**\n     * fDomNode\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @access    public\n     * @property  fDOMDocument $ownerDocument\n     *\n     */\n    class fDOMNode extends \\DOMNode {\n\n        /**\n         * @return string\n         */\n        public function __toString() {\n            return $this->C14N();\n        }\n\n        /**\n         * Create a new fDOMElement\n         *\n         * @see fDOMDocument::createElement\n         *\n         * @param string $name\n         * @param string $content\n         * @param bool $asTextnode\n         *\n         * @return fDOMElement\n         */\n        public function createElement($name, $content = NULL, $asTextnode = FALSE) {\n            return $this->ownerDocument->createElement($name, $content, $asTextnode);\n        }\n\n        /**\n         * Create a new fDOMElement in namespace defined by prefix\n         *\n         * @see fDOMDocument::createElementPrefix\n         *\n         * @param string $prefix\n         * @param string $name\n         * @param string $content\n         * @param bool $asTextNode\n         *\n         * @return fDOMElement\n         */\n        public function createElementPrefix($prefix, $name, $content = NULL, $asTextNode = FALSE) {\n            return $this->ownerDocument->createElementPrefix($prefix, $name, $content, $asTextNode);\n        }\n\n        /**\n         * Create a new fDOMElement within given namespace and return it\n         *\n         * @param string $namespace Namespace URI for node to create\n         * @param string $name Name of node to create\n         * @param null $content Content to set (optional)\n         * @param bool $asTextNode Create content as textNode rather then setting nodeValue\n         *\n         * @throws fDOMException\n         *\n         * @return fDOMElement\n         */\n        public function createElementNS($namespace, $name, $content = NULL, $asTextNode = FALSE) {\n            return $this->ownerDocument->createElementNS($namespace, $name, $content, $asTextNode);\n        }\n\n        /**\n         * Forward to fDomDocument->query()\n         *\n         * @param string   $q               XPath to use\n         * @param \\DOMNode $ctx             \\DOMNode to overwrite context\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return \\DomNodeList\n         */\n        public function query($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->query($q, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n        /**\n         * Forward to fDomDocument->queryOne()\n         *\n         * @param string   $q               XPath to use\n         * @param \\DOMNode $ctx             (optional) \\DOMNode to overwrite context\n         * @param boolean  $registerNodeNS  Register flag pass thru\n         *\n         * @return mixed\n         */\n        public function queryOne($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->queryOne($q, $ctx ? $ctx : $this, $registerNodeNS);\n        }\n\n        /**\n         * Forward to fDomDocument->select()\n         *\n         * @param string   $selector A CSS Level 3 Selector string\n         * @param \\DOMNode $ctx\n         * @param bool     $registerNodeNS\n         *\n         * @return \\DOMNodeList\n         */\n\n        public function select($selector, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            return $this->ownerDocument->select($selector, $ctx, $registerNodeNS);\n        }\n\n        /**\n         * Check if the given node is in the same document\n         *\n         * @param \\DomNode $node Node to compare with\n         *\n         * @return boolean true on match, false if they differ\n         *\n         */\n        public function inSameDocument(\\DOMNode $node) {\n            return $this->ownerDocument->inSameDocument($node);\n        }\n\n        /**\n         * Wrapper to DomDocument::saveXML() with current node as context\n         *\n         * @return string\n         */\n        public function saveXML() {\n            return $this->ownerDocument->saveXML($this);\n        }\n\n        /**\n         * Wrapper to DomDocument::saveHTML() with current node as context\n         *\n         * @return string\n         */\n        public function saveHTML() {\n            return $this->ownerDocument->saveHTML($this);\n        }\n\n\n\n    } // fDOMNode\n\n}\n"
  },
  {
    "path": "src/fDOMXPath.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM {\n\n    /**\n     * fDOMXPath extension to PHP's DOMXPath.\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @access    public\n     *\n     */\n    class fDOMXPath extends \\DOMXPath {\n\n        /**\n         * @var \\DOMDocument\n         */\n        protected $doc;\n\n        /**\n         * @param \\DOMDocument $doc\n         */\n        public function __construct(\\DOMDocument $doc) {\n            parent::__construct($doc);\n            $this->doc = $doc;\n        }\n\n        /**\n         * @param string $xpath\n         * @param array $valueMap\n         *\n         * @return string\n         */\n        public function prepare($xpath, array $valueMap) {\n            if (count($valueMap)==0) {\n                return $xpath;\n            }\n            foreach($valueMap as $key => $value) {\n                $xpath = str_replace(':'.$key, $this->quote($value), $xpath);\n            }\n            return $xpath;\n        }\n\n        /**\n         * @param string $q\n         * @param \\DOMNode $ctx\n         * @param bool $registerNodeNS\n         *\n         * @throws fDOMException\n         *\n         * @return \\DOMNodeList\n         */\n        #[\\ReturnTypeWillChange]\n        public function query($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            libxml_clear_errors();\n            if (version_compare(PHP_VERSION, '5.3.3', '<') || strpos(PHP_VERSION, 'hiphop') || strpos(PHP_VERSION, 'hhvm')) {\n                $rc = parent::query($q, ($ctx instanceof \\DOMNode) ? $ctx : $this->doc->documentElement);\n            } else {\n                $rc = parent::query($q, ($ctx instanceof \\DOMNode) ? $ctx : $this->doc->documentElement, $registerNodeNS);\n            }\n\n            if (libxml_get_last_error()) {\n                throw new fDOMException('evaluating xpath expression failed.', fDOMException::QueryError);\n            }\n            return $rc;\n        }\n\n        /**\n         * @param string $q\n         * @param \\DOMNode $ctx\n         * @param bool $registerNodeNS\n         *\n         * @throws fDOMException\n         *\n         * @return mixed\n         */\n        #[\\ReturnTypeWillChange]\n        public function evaluate($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            libxml_clear_errors();\n            if (version_compare(PHP_VERSION, '5.3.3', '<') || strpos(PHP_VERSION, 'hiphop') || strpos(PHP_VERSION, 'hhvm')) {\n                $rc = parent::evaluate($q, ($ctx instanceof \\DOMNode) ? $ctx : $this->doc->documentElement);\n            } else {\n                $rc = parent::evaluate($q, ($ctx instanceof \\DOMNode) ? $ctx : $this->doc->documentElement, $registerNodeNS);\n            }\n            if (libxml_get_last_error()) {\n                throw new fDOMException('evaluating xpath expression failed.', fDOMException::QueryError);\n            }\n            return $rc;\n        }\n\n        /**\n         * @param string $q\n         * @param \\DOMNode $ctx\n         * @param bool $registerNodeNS\n         *\n         * @throws fDOMException\n         *\n         * @return \\DOMNode|mixed\n         */\n        public function queryOne($q, \\DOMNode $ctx = null, $registerNodeNS = true) {\n            $rc = $this->evaluate($q, $ctx, $registerNodeNS);\n            if ($rc instanceof \\DOMNodelist) {\n                return $rc->item(0);\n            }\n            return $rc;\n        }\n\n        /**\n         * @param string $str\n         *\n         * @return string\n         */\n        public function quote($str) {\n            if (strpos($str, '\"') === false) {\n                return '\"'.$str.'\"';\n            }\n            $parts = explode('\"', $str);\n            return 'concat(\"' . join('\",\\'\"\\',\"', $parts).'\")';\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Translator.test.php",
    "content": "<?php\n\nnamespace TheSeer\\fDOM\\Tests {\n\n    use TheSeer\\fDOM\\CSS\\Translator;\n\n    class TranslatorTest extends \\PHPUnit\\Framework\\TestCase {\n\n        /**\n         * @dataProvider provider\n         */\n        public function testTranslatingCssSelectorReturnsCorrectXPath($selector, $xpath) {\n            $translator = new Translator();\n            $this->assertEquals($xpath, $translator->translate($selector));\n        }\n\n        public function provider() {\n            return array(\n                array(\"div\", '//div'),\n                array(\"body div\", '//body//div'),\n                array(\"div p\", '//div//p'),\n                array(\"div > p\", '//div/p'),\n                array(\"div + p\", '//div/following-sibling::*[1]/self::p'),\n                array(\"div ~ p\", '//div/following-sibling::p'),\n                array(\"div[class^=exa][class$=mple]\", '//div[starts-with(@class,\"exa\") and (substring(@class,string-length(@class)-3)=class)]'),\n                array(\"div p a\", '//div//p//a'),\n                array(\"div, p, a\", '//div|//p|//a'),\n                array(\".note\", '//*[contains(concat(\" \",normalize-space(@class),\" \"),\" note \")]'),\n                array(\"div.example\", '//div[contains(concat(\" \",normalize-space(@class),\" \"),\" example \")]'),\n                array(\"ul .tocline2\", '//ul//*[contains(concat(\" \",normalize-space(@class),\" \"),\" tocline2 \")]'),\n                array(\"div.example, div.note\", '//div[contains(concat(\" \",normalize-space(@class),\" \"),\" example \")]|//div[contains(concat(\" \",normalize-space(@class),\" \"),\" note \")]'),\n                array(\"#title\", '//*[@id=\"title\"]'),\n                array(\"h1#title\", '//h1[@id=\"title\"]'),\n                array(\"div #title\", '//div//*[@id=\"title\"]'),\n                array(\"ul.toc li.tocline2\", '//ul[contains(concat(\" \",normalize-space(@class),\" \"),\" toc \")]//li[contains(concat(\" \",normalize-space(@class),\" \"),\" tocline2 \")]'),\n                array(\"ul.toc > li.tocline2\", '//ul[contains(concat(\" \",normalize-space(@class),\" \"),\" toc \")]/li[contains(concat(\" \",normalize-space(@class),\" \"),\" tocline2 \")]'),\n                array(\"h1#title + div > p\", '//h1[@id=\"title\"]/following-sibling::*[1]/self::div/p'),\n                array(\"h1[id]:contains(Selectors)\", '//h1[@id and (contains(string(.),\"Selectors\"))]'),\n                array(\"a[href][lang][class]\", '//a[@href and (@lang) and (@class)]'),\n                array(\"div[class]\", '//div[@class]'),\n                array(\"div[class=example]\", '//div[@class=\"example\"]'),\n                array(\"div[class^=exa]\", '//div[starts-with(@class,\"exa\")]'),\n                array(\"div[class$=mple]\", '//div[substring(@class,string-length(@class)-3)=class]'),\n                array(\"div[class*=e]\", '//div[contains(@class,\"e\")]'),\n                array(\"div[class|=dialog]\", '//div[@class=\"dialog\" or starts-with(@class,concat(\"dialog\",\"-\"))]'),\n                array(\"div[class!=made_up]\", '//div[not(@class) or @class!=\"made_up\"]'),\n                array(\"div[class~=example]\", '//div[contains(concat(\" \",normalize-space(@class),\" \"),concat(\" \",\"example\",\" \"))]'),\n                array(\"div:not(.example)\", '//div[not(contains(concat(\" \",normalize-space(@class),\" \"),\" example \"))]'),\n                array(\"p:contains(selectors)\", '//p[contains(string(.),\"selectors\")]'),\n                array(\"p:nth-child(even)\", '//*[position() mod 2=0 and position()>=0]/self::p'),\n                array(\"p:nth-child(2n)\", '//*[(position()-) mod 2=0 and position()>=]/self::p'),\n                array(\"p:nth-child(odd)\", '//p[(count(preceding-sibling::*) + 1) mod 2=1]'),\n                array(\"p:nth-child(2n+1)\", '//*[(position()-1) mod 2=0 and position()>=1]/self::p'),\n                array(\"p:nth-child(n)\", '//p'),\n                array(\"p:only-child\", '//*[last()=1]/self::p'),\n                array(\"p:last-child\", '//p[not(following-sibling::*)]'),\n                array(\"p:first-child\", '//*[1]/self::p'),\n                array(\"foo|bar\", '//foo:bar')\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "tests/XPathQuery.test.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM\\Tests {\n\n    use TheSeer\\fDOM\\XPathQuery;\n    use TheSeer\\fDOM\\fDOMDocument;\n    use TheSeer\\fDOM\\XPathQueryException;\n\n    class XPathQueryTest extends \\PHPUnit\\Framework\\TestCase {\n\n        private $dom;\n\n        protected function setUp(): void {\n            $this->dom = new fDOMDocument();\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root attr=\"value\" />');\n        }\n\n\n        public function testFindingKeysInQueryWorks() {\n            $xp = new XPathQuery(':key');\n            $this->assertEquals(array('key'), $xp->getKeys());\n        }\n\n        public function testTryingToBindNonExistingKeyThrowsException() {\n            $xp = new XPathQuery(':key');\n            $this->expectException(XPathQueryException::class);\n            $xp->bind('other', 123);\n        }\n\n        public function testBoundValueForKeyGetsApplied() {\n            $xp = new XPathQuery(':key');\n            $xp->bind('key', 123);\n            $this->assertEquals('\"123\"', $xp->generate($this->dom));\n        }\n\n        public function testAppliedValueForKeyIsUsedOnQueryAndReturnsNode() {\n            $xp = new XPathQuery('//*[@attr = :key]');\n            $xp->bind('key', 'value');\n            $res = $xp->query($this->dom);\n            $this->assertInstanceOf('\\DOMNodelist', $res);\n            $this->assertEquals(1, $res->length);\n            $this->assertInstanceOf('\\DOMNode', $res->item(0));\n        }\n\n        public function testOverwriteValueOnQuery() {\n            $xp = new XPathQuery('//*[@attr = :key]');\n            $xp->bind('key', 'first');\n            $res = $xp->query($this->dom, array('key' => 'value'));\n            $this->assertEquals(1, $res->length);\n            $this->assertInstanceOf('\\DOMNode', $res->item(0));\n        }\n\n        public function testAppliedValueForKeyIsUsedOnEvaluateAndReturnsNode() {\n            $xp = new XPathQuery('//*[@attr = :key]');\n            $xp->bind('key', 'value');\n            $res = $xp->evaluate($this->dom);\n            $this->assertInstanceOf('\\DOMNodelist', $res);\n            $this->assertEquals(1, $res->length);\n            $this->assertInstanceOf('\\DOMNode', $res->item(0));\n        }\n\n        public function testOverwriteValueOnEvaluate() {\n            $xp = new XPathQuery('//*[@attr = :key]');\n            $xp->bind('key', 'first');\n            $res = $xp->evaluate($this->dom, array('key' => 'value'));\n            $this->assertEquals(1, $res->length);\n            $this->assertInstanceOf('\\DOMNode', $res->item(0));\n        }\n\n        public function testCallToQueryOneReturnsOneNode() {\n            $xp = new XPathQuery('//*[@attr]');\n            $res = $xp->queryOne($this->dom);\n            $this->assertInstanceOf('\\DOMNode', $res);\n        }\n\n        public function testQueryCanBeRunWithStandardDomDocument() {\n            $xp = new XPathQuery('/');\n            $res = $xp->query(new \\DomDocument());\n            $this->assertInstanceOf('\\DOMNodelist', $res);\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "tests/_data/broken.xml",
    "content": "<?xml version=\"1.0\" ?>\n<broken>\n<!-- This is broken for testing reasons - do not fix ;) ->\n"
  },
  {
    "path": "tests/_data/selector.xml",
    "content": "<?xml version=\"1.0\" ?>\n<root>\n    <child attr=\"abc\" id=\"test\">\n        <child attr=\"other\" />\n    </child>\n</root>\n"
  },
  {
    "path": "tests/_data/undefentity.xml",
    "content": "<?xml version=\"1.0\" ?>\n<root>&undefined;</root>\n"
  },
  {
    "path": "tests/_data/valid.xml",
    "content": "<?xml version=\"1.0\"?>\n<test/>\n"
  },
  {
    "path": "tests/fDOMDocument.test.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM\\Tests {\n\n    use TheSeer\\fDOM\\fDOMDocument;\n    use TheSeer\\fDOM\\fDOMException;\n\n    /**\n     *\n     * @author     Arne Blankerts <arne@blankerts.de>\n     * @copyright  Arne Blankerts <arne@blankerts.de>, All rights reserved.\n     */\n    class fDOMDocumentTest extends \\PHPUnit\\Framework\\TestCase {\n\n        /**\n         * @var fDOMDocument\n         */\n        private $dom;\n\n        public function setUp(): void {\n            $this->dom = new fDOMDocument();\n        }\n\n        public function testloadingXMLStringWorks() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><test />');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $this->dom->documentElement);\n        }\n\n        public function testloadingXMLFileWorks() {\n            $this->dom->load(__DIR__ . '/_data/valid.xml');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $this->dom->documentElement);\n        }\n\n        public function testGetDomXPathReturnsXPathObject() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><test />');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMXpath', $this->dom->getDomXPath());\n        }\n\n        public function testAttemptingToLoadAnXMLStringWithAnUndefinedEntityThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root>&undefined;</root>');\n        }\n\n        public function testAttemptingToLoadAnEmptyXMLStringThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->loadXML('');\n        }\n\n        public function testAttemptingToLoadWithEmptyFilenameThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->load('');\n        }\n\n        public function testAttemptingToLoadHTMLWithAnEmptyFilenameThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->loadHTMLFile('');\n        }\n\n        public function testAttemptingToLoadHMLWithAnEmptyStringThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->loadHTML('');\n        }\n\n        public function testloadingInvalidXMLStringThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><broken>');\n        }\n\n        public function testTryingToLoadNonExistingFileThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->load('_does_not_exist.xml');\n        }\n\n        public function testloadingBrokenXMLFileThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->load(__DIR__ . '/_data/broken.xml');\n        }\n\n        public function testAttemptingToLoadAnXMLFileWithAnUndefinedEntityThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->load(__DIR__ . '/_data/undefentity.xml');\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::query\n         */\n        public function testQueryReturnsNodeList() {\n            $this->dom->load(__DIR__ . '/_data/valid.xml');\n            $list = $this->dom->query('/test');\n            $this->assertInstanceOf('DomNodelist', $list);\n            $this->assertEquals(1, $list->length);\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::queryOne\n         */\n        public function testQueryOneReturnsElement() {\n            $this->dom->load(__DIR__ . '/_data/valid.xml');\n            $node = $this->dom->queryOne('/test');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n        }\n\n        public function testSaveXMLReturnsCorrectXMLString() {\n            $xml = file_get_contents(__DIR__ . '/_data/valid.xml');\n            $this->dom->loadXML($xml);\n            $this->assertEquals($xml, $this->dom->saveXML());\n        }\n\n        public function testSaveXMLThrowsExceptionWithReferenceToNodeFromOtherDocument() {\n            $dom = new fDOMDocument();\n            $this->expectException(fDOMException::class);\n            $this->dom->saveXML($dom->createElement('foo'));\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::nodeList2FragMent\n         */\n        public function testTransformNodeListToFragmentWorks() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root><node1/><node2 /></root>');\n            $frag = $this->dom->nodeList2Fragment($this->dom->query('/root/*'));\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMDocumentFragment', $frag);\n            $this->assertEquals(2, $frag->childNodes->length);\n        }\n\n        public function testPrepareQueryReturnsValidXPathString() {\n            $values = array('key' => 'the \"value\" of \\'values\\'');\n            $xpath = '//some[@value = :key]';\n            $result = $this->dom->prepareQuery($xpath, $values);\n            $this->assertEquals('//some[@value = concat(\"the \",\\'\"\\',\"value\",\\'\"\\',\" of \\'values\\'\")]', $result);\n        }\n\n        public function testRegisteringANamespaceWithPrefixWorks() {\n            $this->dom->registerNamespace('test', 'test:uri');\n            $this->assertAttributeEquals(array('test' => 'test:uri'), 'prefixes', $this->dom);\n        }\n\n        public function testCreatingElementWithInvalidNameThrowsException() {\n            $this->expectException(fDOMException::class);\n            $node = $this->dom->createElement('in valid');\n        }\n\n        public function testCreatingElementWithoutText() {\n            $node = $this->dom->createElement('name');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals('name', $node->nodeName);\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::createElementPrefix\n         */\n        public function testCreatingNewElementByprefix() {\n            $this->dom->registerNamespace('test', 'test:uri');\n            $node = $this->dom->createElementPrefix('test', 'node');\n            $this->assertEquals('test:uri', $node->namespaceURI);\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::createElementPrefix\n         */\n        public function testTryingToCreateNewElementByprefixWithUndefinedPrefixThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->dom->createElementPrefix('test', 'node');\n        }\n\n        public function testSettingContentUnescapedForNewElementRemainsIntact() {\n            $node = $this->dom->createElement('test', \"test &amp; demo\");\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testSettingContentUnescapedForNewElementThrowsExceptionOnInvalidEntity() {\n            $this->expectException(fDOMException::class);\n            $node = $this->dom->createElement('test', \"test & demo\");\n        }\n\n        public function testSettingContentAsTextNodeForNewElementEncodesEntities() {\n            $node = $this->dom->createElement('test', \"test &amp; demo\", TRUE);\n            $this->assertEquals('test &amp; demo', $node->nodeValue);\n        }\n\n        public function testSettingContentUnescapedForNewElementWithNamespaceRemainsIntact() {\n            $node = $this->dom->createElementNS('test:uri', 'test', \"test &amp; demo\");\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testSettingContentUnescapedForNewElementWithNamespaceThrowsExceptionOnInvalidEntity() {\n            $this->expectException(fDOMException::class);\n            $node = $this->dom->createElementNS('test:uri', 'test', \"test & demo\");\n        }\n\n        public function testSettingContentAsTextNodeForNewElementWithNamespaceEncodesEntities() {\n            $node = $this->dom->createElementNS('test:uri', 'test', \"test &amp; demo\", TRUE);\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals('test &amp; demo', $node->nodeValue);\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::queryOne\n         */\n        public function testThatTwoNodesAreIdentifiedAsBeingInTheSameDocument() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root><node /></root>');\n            $node = $this->dom->queryOne('//node');\n            $this->assertTrue($this->dom->inSameDocument($node));\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::inSameDocument\n         */\n        public function testThatANodeFromADifferentDocumentIsNotConsideredAsInSameDocument() {\n            $dom = new fDOMDocument();\n            $node = $dom->createElement('foo');\n\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root />');\n            $this->assertFalse($this->dom->documentElement->inSameDocument($node));\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::inSameDocument\n         */\n        public function testInSameDocumentWorksForDOMDocument() {\n            $dom = new fDOMDocument();\n            $this->assertFalse($this->dom->inSameDocument($dom));\n        }\n\n        public function testAppendElementCreatesANewNodeAndAttachesIt() {\n            $node = $this->dom->appendElement('test');\n            $this->assertSame($node, $this->dom->documentElement);\n        }\n\n        public function testAppendElementNSCreatesANewNodeAndAttachesIt() {\n            $node = $this->dom->appendElementNS('test:uri', 'test');\n            $this->assertSame($node, $this->dom->documentElement);\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::__clone\n         */\n        public function testCloningTriggersCreationOfNewDOMXPathInstance() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><test />');\n            $xp1 = $this->dom->getDOMXPath();\n            $clone = clone $this->dom;\n            $xp2 = $clone->getDOMXPath();\n            $this->assertNotSame($xp2, $xp1);\n        }\n\n        /**\n         * @covers \\TheSeer\\fDOM\\fDOMDocument::__clone\n         */\n        public function testRegisteredNamespacePrefixesGetCopiedToClonedDocument() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><foo:test xmlns:foo=\"test:uri\" />');\n            $this->dom->registerNamespace('foo', 'test:uri');\n\n            $clone = clone $this->dom;\n\n            $node = $clone->queryOne('//foo:test');\n            $this->assertSame($clone->documentElement, $node);\n        }\n\n        /**\n         * https://github.com/theseer/fDOMDocument/issues/15\n         */\n        public function testQueryReturnsNodeFromClonedDocument() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><test />');\n            $clone = clone $this->dom;\n\n            $node = $clone->queryOne('/test');\n            $this->assertNotSame($this->dom->documentElement, $node);\n\n        }\n\n        public function testCSSSelectorReturnsCorrectNodes() {\n            $this->dom->load(__DIR__ . '/_data/selector.xml');\n            $result = $this->dom->select('child');\n            $this->assertEquals(2, $result->length);\n            $this->assertEquals('child', $result->item(0)->nodeName);\n            $this->assertEquals('child', $result->item(1)->nodeName);\n        }\n\n        public function testCSSSelectorHonorsContextNode() {\n            $this->dom->load(__DIR__ . '/_data/selector.xml');\n            $ctx = $this->dom->getElementsByTagName('child')->item(0);\n            $result = $this->dom->select('child', $ctx);\n            $this->assertEquals(1, $result->length);\n            $this->assertEquals('child', $result->item(0)->nodeName);\n            $this->assertEquals('other', $result->item(0)->getAttribute('attr'));\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "tests/fDOMDocumentFragment.test.php",
    "content": "<?php\n/**\n * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *\n *   * Redistributions in binary form must reproduce the above copyright notice,\n *     this list of conditions and the following disclaimer in the documentation\n *     and/or other materials provided with the distribution.\n *\n *   * Neither the name of Arne Blankerts nor the names of contributors\n *     may be used to endorse or promote products derived from this software\n *     without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n *\n * @category  PHP\n * @package   TheSeer\\fDOM\n * @author    Arne Blankerts <arne@blankerts.de>\n * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n * @link      http://github.com/theseer/fdomdocument\n *\n */\n\nnamespace TheSeer\\fDOM\\Tests {\n\n    use TheSeer\\fDOM\\fDOMDocument;\n    use TheSeer\\fDOM\\fDOMDocumentFragment;\n    use TheSeer\\fDOM\\fDOMException;\n\n    /**\n     *\n     * @author     Arne Blankerts <arne@blankerts.de>\n     * @copyright  Arne Blankerts <arne@blankerts.de>, All rights reserved.\n     */\n    class fDOMDocumentFragmentTest extends \\PHPUnit\\Framework\\TestCase {\n\n        /**\n         * @var fDOMDocument\n         */\n        private $dom;\n\n        /**\n         * @var fDOMDocumentFragment\n         */\n        private $frag;\n\n        public function setUp(): void {\n            $this->dom = new fDOMDocument();\n            $this->frag = $this->dom->createDocumentFragment();\n        }\n\n        public function testAppendedXMLGetsAddedAndIsParsedAsXML() {\n            $this->frag->appendXML('<some />');\n            $this->assertEquals('some', $this->frag->firstChild->nodeName);\n        }\n\n        public function testTryingToAppendInvalidXMLToFragmentThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->frag->appendXML('<foo');\n        }\n\n        public function testCheckingInSameDocumentReturnsTrueOnNodeFromFragment() {\n            $this->frag->appendXML('<some />');\n            $this->assertTrue($this->frag->inSameDocument($this->frag->firstChild));\n        }\n\n        public function testAppendingANewElement() {\n            $node = $this->frag->appendElement('append', 'text');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->frag->query('count(append)'));\n            $this->assertEquals('text', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespace() {\n            $node = $this->frag->appendElementNS('test:uri', 'append', 'text');\n            $this->dom->registerNamespace('t', 'test:uri');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->frag->query('count(t:append)'));\n            $this->assertEquals('text', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespaceByPrefix() {\n            $this->dom->registerNamespace('t', 'test:uri');\n            $node = $this->frag->appendElementPrefix('t', 'append', 'text');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->frag->query('count(t:append)'));\n            $this->assertEquals('text', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespaceAsTextNodeByPrefix() {\n            $this->dom->registerNamespace('t', 'test:uri');\n            $node = $this->frag->appendElementPrefix('t', 'append', 'test & demo', true);\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->frag->query('count(t:append)'));\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testAppendingATextAsTextnode() {\n            $node = $this->frag->appendTextNode('test & demo');\n            $found = $this->frag->queryOne('text()');\n            $this->assertSame($node, $found);\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testCSSSelectorReturnsCorrectNodes() {\n            $node = $this->frag->appendElement('append', 'text');\n            $result = $this->frag->select('append');\n            $this->assertSame($node, $result->item(0));\n            $this->assertEquals(1, $result->length);\n        }\n\n        public function testToStringReturnsSerializedXMLString() {\n            $this->frag->appendElement('append', 'text');\n            $this->assertEquals('<append>text</append>', (string)$this->frag);\n        }\n\n    }\n}\n"
  },
  {
    "path": "tests/fDOMElement.test.php",
    "content": "<?php\n    /**\n     * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n     * All rights reserved.\n     *\n     * Redistribution and use in source and binary forms, with or without modification,\n     * are permitted provided that the following conditions are met:\n     *\n     *   * Redistributions of source code must retain the above copyright notice,\n     *     this list of conditions and the following disclaimer.\n     *\n     *   * Redistributions in binary form must reproduce the above copyright notice,\n     *     this list of conditions and the following disclaimer in the documentation\n     *     and/or other materials provided with the distribution.\n     *\n     *   * Neither the name of Arne Blankerts nor the names of contributors\n     *     may be used to endorse or promote products derived from this software\n     *     without specific prior written permission.\n     *\n     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n     * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n     * POSSIBILITY OF SUCH DAMAGE.\n     *\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n     * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n     * @link      http://github.com/theseer/fdomdocument\n     *\n     */\n\nnamespace TheSeer\\fDOM\\Tests {\n\n    use TheSeer\\fDOM\\fDOMDocument;\n    use TheSeer\\fDOM\\fDOMElement;\n\n    /**\n     *\n     * @author     Arne Blankerts <arne@blankerts.de>\n     * @copyright  Arne Blankerts <arne@blankerts.de>, All rights reserved.\n     */\n    class fDOMElementTest extends \\PHPUnit\\Framework\\TestCase {\n\n        /**\n         * @var fDOMDocument\n         */\n        private $dom;\n\n        /**\n         * @var fDOMElement\n         */\n        private $node;\n\n        public function setUp(): void {\n            $this->dom = new fDOMDocument();\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root><node><child/></node><node /></root>');\n            $this->node = $this->dom->documentElement;\n        }\n\n        /**\n         * The query is a forwarder to the DOMDocument, so just checking if the forwarding works is enough\n         */\n        public function testQueryReturnsNodelist() {\n            $list = $this->node->query('//node');\n            $this->assertInstanceOf('DOMNodelist', $list);\n            $this->assertEquals(2, $list->length);\n        }\n\n        /**\n         * The query is a forwarder to the DOMDocument, so just checking if the forwarding works is enough\n         */\n        public function testQueryOneReturnsNode() {\n            $node = $this->node->queryOne('//root');\n            $this->assertSame($this->node, $node);\n        }\n\n        public function testAppendingAnXMLStringCreatesAFragment() {\n            $frag = $this->node->appendXML('<append />');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMDocumentFragment', $frag);\n            $this->assertEquals(1, $this->node->query('count(append)'));\n        }\n\n        public function testAppendingANewElement() {\n            $node = $this->node->appendElement('append', 'text');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->node->query('count(append)'));\n            $this->assertEquals('text', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementAsTextNode() {\n            $node = $this->node->appendElement('append', 'test & demo', true);\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->node->query('count(append)'));\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespace() {\n            $node = $this->node->appendElementNS('test:uri', 'append', 'text');\n            $this->dom->registerNamespace('t','test:uri');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->node->query('count(t:append)'));\n            $this->assertEquals('text', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespaceAsTextNode() {\n            $node = $this->node->appendElementNS('test:uri', 'append', 'test & demo', true);\n            $this->dom->registerNamespace('t','test:uri');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->node->query('count(t:append)'));\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespaceByPrefix() {\n            $this->dom->registerNamespace('t','test:uri');\n            $node = $this->node->appendElementPrefix('t', 'append', 'text');\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->node->query('count(t:append)'));\n            $this->assertEquals('text', $node->nodeValue);\n        }\n\n        public function testAppendingANewElementWithinANamespaceAsTextNodeByPrefix() {\n            $this->dom->registerNamespace('t','test:uri');\n            $node = $this->node->appendElementPrefix('t', 'append', 'test & demo', true);\n            $this->assertInstanceOf('TheSeer\\fDOM\\fDOMElement', $node);\n            $this->assertEquals(1, $this->node->query('count(t:append)'));\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testAppendingATextAsTextnode() {\n            $node = $this->node->appendTextNode('test & demo');\n            $found = $this->node->queryOne('text()');\n            $this->assertSame($node, $found);\n            $this->assertEquals('test & demo', $node->nodeValue);\n        }\n\n        public function testGettingNonExistingAttributeReturnsDefaultValue() {\n            $res = $this->node->getAttribute('missing','default');\n            $this->assertEquals('default', $res);\n        }\n\n        public function testGettingNonExistingAttributeWithNamespaceReturnsDefaultValue() {\n            $res = $this->node->getAttributeNS('some:uri', 'missing','default');\n            $this->assertEquals('default', $res);\n        }\n\n        public function testSettingAttributeValueWithPlainValue() {\n            $attr = $this->node->setAttribute('test', 'value');\n            $this->assertTrue($this->node->hasAttribute('test'));\n            $this->assertInstanceOf('DOMAttr', $attr);\n            $this->assertEquals('value', $this->node->getAttribute('test'));\n        }\n\n        public function testSettingAttributeValueWithEntitiesEncodesProperly() {\n            $attr = $this->node->setAttribute('test', '&amp;');\n            $this->assertTrue($this->node->hasAttribute('test'));\n            $this->assertInstanceOf('DOMAttr', $attr);\n            $this->assertEquals('&amp;', $this->node->getAttribute('test'));\n        }\n\n        public function testSettingAttributeValueWithEntitiesAndKeepEntitiesEnabledDoesNotEncode() {\n            $attr = $this->node->setAttribute('test', '&amp;', true);\n            $this->assertTrue($this->node->hasAttribute('test'));\n            $this->assertInstanceOf('DOMAttr', $attr);\n            $this->assertEquals('&', $this->node->getAttribute('test'));\n        }\n\n        public function testSettingNamespacedAttributeValueWithPlainValue() {\n            $this->node->setAttributeNS('some:uri','s:attr', 'value');\n            $this->assertTrue($this->node->hasAttributeNS('some:uri','attr'));\n            $this->assertEquals('value', $this->node->getAttributeNS('some:uri','attr'));\n        }\n\n        public function testSettingNamespacedAttributeValueWithEntitiesEncodesProperly() {\n            $this->node->setAttributeNS('test:uri', 't:test', '&amp;');\n            $this->assertTrue($this->node->hasAttributeNS('test:uri', 'test'));\n            $this->assertEquals('&amp;', $this->node->getAttributeNS('test:uri','test'));\n        }\n\n        public function testSettingNamespacedAttributeValueWithEntitiesAndKeepEntitiesEnabledDoesNotEncode() {\n            $attr = $this->node->setAttributeNS('test:uri', 't:test', '&amp;', true);\n            $this->assertTrue($this->node->hasAttributeNS('test:uri', 'test'));\n            $this->assertInstanceOf('DOMAttr', $attr);\n            $this->assertEquals('&', $this->node->getAttributeNS('test:uri', 'test'));\n        }\n\n        public function testSettingMultipleAttributesFromArray() {\n            $attrs = array('a1' => 'v1', 'a2' => 'v2');\n            $this->node->setAttributes($attrs);\n            $this->assertEquals('v1', $this->node->getAttribute('a1'));\n            $this->assertEquals('v2', $this->node->getAttribute('a2'));\n        }\n\n        public function testSettingMultipleAttributesWithNamespaceFromArray() {\n            $attrs = array('a1' => 'v1', 'a2' => 'v2');\n            $this->node->setAttributesNS('some:uri','s', $attrs);\n            $this->assertEquals('v1', $this->node->getAttributeNS('some:uri', 'a1'));\n            $this->assertEquals('v2', $this->node->getAttributeNS('some:uri', 'a2'));\n        }\n\n        public function testGetChildrenByTagnameReturnsCorrectNodelist() {\n            $list = $this->node->getChildrenByTagName('node');\n            $this->assertInstanceOf('DOMNodeList', $list);\n            $this->assertEquals(2, $list->length);\n        }\n\n        public function testGetChildrenByTagnameNSReturnsCorrectNodelist() {\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root xmlns=\"test:uri\"><node><child/></node><node /></root>');\n            $this->node = $this->dom->documentElement;\n            $list = $this->node->getChildrenByTagNameNS('test:uri', 'node');\n            $this->assertInstanceOf('DOMNodeList', $list);\n            $this->assertEquals(2, $list->length);\n        }\n\n        public function testInSameDocumentForwardsToOwnerDocumentAndReturnsCorrectValue() {\n            $rc = $this->node->inSameDocument($this->node->firstChild);\n            $this->assertTrue($rc);\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "tests/fDOMXPath.test.php",
    "content": "<?php\n    /**\n     * Copyright (c) 2010-2017 Arne Blankerts <arne@blankerts.de>\n     * All rights reserved.\n     *\n     * Redistribution and use in source and binary forms, with or without modification,\n     * are permitted provided that the following conditions are met:\n     *\n     *   * Redistributions of source code must retain the above copyright notice,\n     *     this list of conditions and the following disclaimer.\n     *\n     *   * Redistributions in binary form must reproduce the above copyright notice,\n     *     this list of conditions and the following disclaimer in the documentation\n     *     and/or other materials provided with the distribution.\n     *\n     *   * Neither the name of Arne Blankerts nor the names of contributors\n     *     may be used to endorse or promote products derived from this software\n     *     without specific prior written permission.\n     *\n     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  * NOT LIMITED TO,\n     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS\n     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n     * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n     * POSSIBILITY OF SUCH DAMAGE.\n     *\n     *\n     * @category  PHP\n     * @package   TheSeer\\fDOM\n     * @author    Arne Blankerts <arne@blankerts.de>\n     * @copyright Arne Blankerts <arne@blankerts.de>, All rights reserved.\n     * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License\n     * @link      http://github.com/theseer/fdomdocument\n     *\n     */\n\nnamespace TheSeer\\fDOM\\Tests {\n\n    use TheSeer\\fDOM\\fDOMDocument;\n    use TheSeer\\fDOM\\fDOMException;\n    use TheSeer\\fDOM\\fDOMXPath;\n\n    /**\n     *\n     * @author     Arne Blankerts <arne@blankerts.de>\n     * @copyright  Arne Blankerts <arne@blankerts.de>, All rights reserved.\n     */\n    class fDOMXPathTest extends \\PHPUnit\\Framework\\TestCase {\n\n        /**\n         * @var TheSeer\\fDOM\\fDOMDocument\n         */\n        private $dom;\n\n        /**\n         * @var TheSeer\\fDOM\\fDOMXPath\n         */\n        private $xp;\n\n        public function setUp(): void {\n            $this->dom = new fDOMDocument();\n            $this->dom->loadXML('<?xml version=\"1.0\" ?><root><node attr=\"foo\" /></root>');\n            $this->xp = $this->dom->getDOMXPath();\n        }\n\n        /**\n         * @covers TheSeer\\fDOM\\fDOMXPath::query\n         */\n        public function testExecutingAQueryWithInvalidXPathThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->xp->query('//[invalid');\n\n        }\n\n\n        public function testQueryReturnsNodeList() {\n            $res = $this->xp->query('//*');\n            $this->assertInstanceOf('DOMNodeList', $res);\n            $this->assertEquals(2, $res->length);\n        }\n\n        /**\n         * @covers TheSeer\\fDOM\\fDOMXPath::evaluate\n         */\n        public function testExecutingAQueryWithEvaluateWithInvalidXPathThrowsException() {\n            $this->expectException(fDOMException::class);\n            $this->xp->evaluate('//[invalid');\n        }\n\n        /**\n         * @covers TheSeer\\fDOM\\fDOMXPath::quote\n         */\n        public function testPrepareReturnsStraightStringOnPlainText() {\n            $this->assertEquals('\"test\"', $this->xp->quote('test'));\n        }\n\n        public function testQueryOneReturnsANode() {\n            $this->assertSame($this->dom->documentElement, $this->xp->queryOne('//root'));\n        }\n\n        public function testPrepareReturnsUnmodifiedXPathOnEmptyArray() {\n            $xpath = 'test';\n            $this->assertEquals($xpath, $this->xp->prepare($xpath, array()));\n        }\n\n        public function testQueryOneReturnsValueOnNonNodeQuery() {\n            $this->assertEquals('1', $this->xp->queryOne('count(//root)'));\n        }\n\n    }\n\n}\n"
  }
]