[FEATURE] Remove ViewHelper xmlns-attributes and specified html tag 72/38472/43
authorAndreas Allacher <andreas.allacher@gmx.at>
Sat, 4 Apr 2015 05:24:56 +0000 (05:24 +0000)
committerFrank Nägler <typo3@naegler.net>
Mon, 1 Jun 2015 15:45:49 +0000 (17:45 +0200)
In order to include ViewHelper namespaces with xmlns:*-attributes
it is currently required to use e.g. a HTML tag to allow code-completion
by an IDE. The tag itself will also be rendered.
To avoid rending the tag, workarounds are necessary.
One is to use sections, but this approach is counter-intuitive and has
rendering overhead due to extra sections being used. Additionally it is
not possible to use this workaround in layouts.

This patch introduces new functionality to remove all xmlns-attributes
which match ViewHelper namespaces.
For HTML output, we introduce a new attribute, which will cause Fluid
to remove the HTML-tag as well.
The attributes is called >data-namespace-typo3-fluid="true"<

Change-Id: I709d17da86cd79b7b3ba5c83b3f2bd6df8e2bd98
Releases: master
Resolves: #66269
Reviewed-on: http://review.typo3.org/38472
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Daniel Schmidt <daniel@netz-basis.com>
Tested-by: Daniel Schmidt <daniel@netz-basis.com>
Reviewed-by: Frank Nägler <typo3@naegler.net>
Tested-by: Frank Nägler <typo3@naegler.net>
typo3/sysext/core/Documentation/Changelog/master/Feature-66269-FluidRemoveViewHelperXmlnsAttributesAndSpecifiedHtmlTag.rst [new file with mode: 0644]
typo3/sysext/fluid/Classes/Core/Parser/TemplateParser.php
typo3/sysext/fluid/Tests/Unit/Core/Parser/TemplateParserTest.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-66269-FluidRemoveViewHelperXmlnsAttributesAndSpecifiedHtmlTag.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-66269-FluidRemoveViewHelperXmlnsAttributesAndSpecifiedHtmlTag.rst
new file mode 100644 (file)
index 0000000..b861b3a
--- /dev/null
@@ -0,0 +1,103 @@
+==================================================================================
+Feature - #66269: Fluid: Remove ViewHelper xmlns-attributes and specified html tag
+==================================================================================
+
+Description
+===========
+
+With the introduction of using xmlns:* attributes to include ViewHelpers, it is possible to have IDE support for Fluid templates.
+However, the problem is that the xmlns:* attributes and the corresponding tag will also be rendered, which is not desired
+most of the time. A workaround, to avoid this is, is to use sections.
+However, this solution is counter-intuitive, is not available in layouts and causes extra processing overhead.
+
+.. code-block:: html
+
+       <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                       xmlns:n="http://typo3.org/ns/GeorgRinger/News/ViewHelpers">
+
+       <f:section name="content">
+       </f:section>
+
+
+Impact
+======
+
+The xmlns:* attributes for valid ViewHelper namespaces will now be removed before rendering.
+Such ViewHelper namespaces follow this URI pattern:
+
+.. code-block:: html
+
+       http://typo3.org/ns/<phpNamespace>
+
+
+Examples:
+
+.. code-block:: html
+
+       http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers
+       http://typo3.org/ns/GeorgRinger/News/ViewHelpers
+
+
+xmlns attributes for non-ViewHelper namespaces will be preserved.
+
+Furthermore an additional data-attribute to HTML-Tags is introduced.
+
+.. code-block:: html
+
+       data-namespace-typo3-fluid="true"
+
+If this attribute is specified on the HTML-Tag, the HTML-tag itself won't be rendered as well.
+(Also a corresponding closing tag will not be rendered for that template.)
+This is useful for various IDEs and HTML autocompletion.
+
+
+Examples
+========
+
+Include ViewHelper namespaces on an existing tag (e.g. root xml tag) via xmlns attributes for Fluid and News extension.
+
+.. code-block:: xml
+
+       <?xml version="1.0" encoding="utf-8"?>
+       <root xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                       xmlns:n="http://typo3.org/ns/GeorgRinger/News/ViewHelpers"
+                       xmlns:foo="http://typo3.org/foo">
+
+               <f:if condition="{newsItem.title}">
+                       <f:then>
+                               <n:titleTag>{newsItem.title}</n:titleTag>
+                       </f:then>
+                       <f:else>
+                               <n:titleTag>News-Detail</n:titleTag>
+                       </f:else>
+               </f:if>
+       </root>
+
+Output is then
+
+.. code-block:: xml
+
+       <root xmlns:foo="http://typo3.org/foo" >
+               ...
+       </root>
+
+
+Include ViewHelper namespaces with HTML-tag and a data-namespace-typo3-fluid="true" attribute via xmlns attributes for Fluid and News extension.
+
+.. code-block:: html
+
+       <html data-namespace-typo3-fluid="true"
+                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                       xmlns:n="http://typo3.org/ns/GeorgRinger/News/ViewHelpers">
+
+               <f:if condition="{newsItem.title}">
+                       <f:then>
+                               <n:titleTag>{newsItem.title}</n:titleTag>
+                       </f:then>
+                       <f:else>
+                               <n:titleTag>News-Detail</n:titleTag>
+                       </f:else>
+               </f:if>
+       </html>
+
+The output contains everything excluding the HTML-tag.
index d0821a7..658a3c1 100644 (file)
@@ -83,6 +83,26 @@ class TemplateParser {
        static public $SCAN_PATTERN_TEMPLATE_CLOSINGVIEWHELPERTAG = '/^<\\/(?P<NamespaceIdentifier>NAMESPACE):(?P<MethodIdentifier>[a-zA-Z0-9\\.]+)\\s*>$/';
 
        /**
+        * This regular expression scans for HTML tags that have the attribute
+        * data-namespace-typo3-fluid="true".
+        * If this attribute is added to the HTML tag, the HTML tag will be removed
+        * from the rendered output.
+        */
+       static public $SCAN_PATTERN_NAMESPACE_FLUID_HTML_TAG = '/<html\\s++[^>]*data-namespace-typo3-fluid="true"[^>]*>/m';
+
+       /**
+        * This regular expression is used to remove xmlns attributes that are used
+        * to register ViewHelper namespaces.
+        *
+        * Replaces trailing empty spaces to avoid additional new lines that might be in the the tag.
+        * It is therefore necessary to replace the pattern with space instead of empty string.
+        *
+        * Searches for multiple xmlns declarations after one another to only replace them with one space,
+        * instead of one per xmlns definition.
+        */
+       static public $SCAN_PATTERN_REMOVE_VIEWHELPERS_XMLNSDECLARATIONS = '/(?:\\s*+xmlns:(?:%1$s)="[^"]*"\\s*+)++/m';
+
+       /**
         * This regular expression splits the tag arguments into its parts
         */
        static public $SPLIT_PATTERN_TAGARGUMENTS = '/
@@ -370,10 +390,12 @@ class TemplateParser {
         */
        protected function extractNamespaceDefinitions($templateString) {
                $matches = array();
+               $foundIdentifiers = array();
                preg_match_all(self::$SCAN_PATTERN_XMLNSDECLARATION, $templateString, $matches, PREG_SET_ORDER);
                foreach ($matches as $match) {
                                // skip reserved "f" namespace identifier
                        if ($match['identifier'] === 'f') {
+                               $foundIdentifiers[] = 'f';
                                continue;
                        }
                        if (array_key_exists($match['identifier'], $this->namespaces)) {
@@ -388,8 +410,12 @@ class TemplateParser {
                                }
                                $phpNamespace = str_replace('/', '\\', $matchedPhpNamespace['PhpNamespace']);
                        }
+                       $foundIdentifiers[] = $match['identifier'];
                        $this->namespaces[$match['identifier']] = $phpNamespace;
                }
+
+               $templateString = $this->removeXmlnsViewHelperNamespaceDeclarations($templateString, $foundIdentifiers);
+
                $matches = array();
                preg_match_all(self::$SCAN_PATTERN_NAMESPACEDECLARATION, $templateString, $matches, PREG_SET_ORDER);
                foreach ($matches as $match) {
@@ -406,6 +432,38 @@ class TemplateParser {
        }
 
        /**
+        * Removes html-tag (opening & closing) that is only used for xmlns definition
+        * and xmlns attributes that register ViewHelpers on any tags
+        *
+        * @param string $templateString
+        * @param array $foundIdentifiers
+        * @return string
+        */
+       protected function removeXmlnsViewHelperNamespaceDeclarations($templateString, array $foundIdentifiers) {
+               $foundHtmlTags = 0;
+               $templateString = preg_replace(self::$SCAN_PATTERN_NAMESPACE_FLUID_HTML_TAG, '', $templateString, 1, $foundHtmlTags);
+               if ($foundHtmlTags > 0) {
+                       $templateString = str_replace('</html>', '', $templateString);
+               }
+
+               if (!empty($foundIdentifiers)) {
+                       $foundIdentifiers = array_map(function($foundIdentifier) {
+                               return preg_quote($foundIdentifier, '/');
+                       }, $foundIdentifiers);
+                       $foundIdentifiers = implode('|', $foundIdentifiers);
+
+                       // replaces the pattern with space because the pattern includes trailing spaces and consecutive xmlns ViewHelper defintions
+                       $templateString = preg_replace(
+                               sprintf(self::$SCAN_PATTERN_REMOVE_VIEWHELPERS_XMLNSDECLARATIONS, $foundIdentifiers),
+                               ' ',
+                               $templateString
+                       );
+               }
+
+               return $templateString;
+       }
+
+       /**
         * Splits the template string on all dynamic tags found.
         *
         * @param string $templateString Template string to split.
index 08a3d8b..f8b9f72 100644 (file)
@@ -10,6 +10,8 @@ namespace TYPO3\CMS\Fluid\Tests\Unit\Core\Parser;
  *                                                                        *
  * The TYPO3 project - inspiring people to share!                         *
  *                                                                        */
+use TYPO3\CMS\Fluid\Core\Parser\TemplateParser;
+use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
 
 /**
  * Testcase for TemplateParser.
@@ -148,6 +150,413 @@ class TemplateParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        }
 
        /**
+        * @param array $expectedFoundIdentifiers
+        * @param string $templateString
+        * @param array $namespaces
+        * @test
+        * @dataProvider extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiersDataProvider
+        */
+       public function extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiers(array $expectedFoundIdentifiers, $templateString, array $namespaces) {
+               $mockSettings = array(
+                       'namespaces' => $namespaces
+               );
+
+               /** @var TemplateParser|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $templateParser */
+               $templateParser = $this->getAccessibleMock(TemplateParser::class, array('removeXmlnsViewHelperNamespaceDeclarations'));
+               $templateParser->injectSettings($mockSettings);
+
+               // this verifies that the method is called with the correct found identifiers
+               // and also that the templateString was not modified before calling removeXmlnsViewHelperNamespaceDeclarations
+               $templateParser
+                       ->expects($this->once())
+                       ->method('removeXmlnsViewHelperNamespaceDeclarations')
+                       ->with($templateString, $expectedFoundIdentifiers)
+                       ->willReturnArgument(0);
+               $templateParser->_call('extractNamespaceDefinitions', $templateString);
+       }
+
+       /**
+        * @return array
+        */
+       public function extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiersDataProvider() {
+               return [
+                       'bothViewHelperNamespacesDefinitionsOnlyProvideXmlnsViewHelpersUsingNonDefaultPatternViewHelpers' => array(
+                               ['foo'],
+                               '{namespace typo3=TYPO3\\CMS\\Fluid\\Blablubb} <div xmlns:foo="http://domain.tld/ns/foo/viewhelpers">Content</div>',
+                               ['http://domain.tld/ns/foo/viewhelpers' => 'My\\Namespace']
+                       ),
+                       'bothViewHelperNamespacesDefinitionsOnlyProvideXmlnsViewHelpersUsingDefaultPatternViewHelpers' => array(
+                               ['xyz'],
+                               '{namespace typo3=TYPO3\\CMS\\Fluid\\Blablubb} <div xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">Content</div>',
+                               []
+                       ),
+                       'xmlnsIdentifiersWithWhitespaces' => array(
+                               [' ', 'foo bar', '"x y z"'],
+                               '
+                                       <div xmlns: ="http://typo3.org/ns/Some/Package/ViewHelpers"
+                                                       xmlns:foo bar="http://domain.tld/ns/foobar/viewhelpers"
+                                                       xmlns:"x y z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
+
+                                               Content
+                                       </div>
+                               ',
+                               ['http://domain.tld/ns/foobar/viewhelpers' => 'My\\Namespace']
+                       ),
+                       'xmlnsWithEqualsSign' => array(
+                               ['=', 'foo=bar', '"x=y=z"'],
+                               '
+                                       <div xmlns:=="http://typo3.org/ns/Some/Package/ViewHelpers"
+                                                       xmlns:foo=bar="http://domain.tld/ns/foobar/viewhelpers"
+                                                       xmlns:"x=y=z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
+
+                                               Content
+                                       </div>
+                               ',
+                               ['http://domain.tld/ns/foobar/viewhelpers' => 'My\\Namespace']
+                       ),
+                       'nonViewHelpersXmlnsAreNotIncludedButDefaultPatternAndNonDefaultAreIncluded' => array(
+                               ['xyz', 'foo'],
+                               '<div xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers"
+                                               xmlns:foo="http://domain.tld/ns/foo/viewhelpers"
+                                               xmlns:bar="http://typo3.org/foo/bar">
+
+                                       Content
+                               </div>',
+                               ['http://domain.tld/ns/foo/viewhelpers' => 'My\\Namespace']
+                       ),
+                       'nonViewHelpersInBetweenViewHelperXmlnsAreNotIncludedButDefaultPatternAndNonDefaultAreIncluded' => array(
+                               ['xyz', 'foo'],
+                               '<div xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers"
+                                                       xmlns:bar="http://typo3.org/foo/bar"
+                                                       xmlns:foo="http://domain.tld/ns/foo/viewhelpers">
+
+                                       Content
+                               </div>',
+                               ['http://domain.tld/ns/foo/viewhelpers' => 'My\\Namespace']
+                       ),
+                       'fluidNamespaceIsFound' => array(
+                               ['f'],
+                               '<div xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">Content</div>',
+                               []
+                       ),
+                       'xmlnsWithoutIdentifierIsIgnored' => array(
+                               [],
+                               '<div xmlns="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">Content</div>',
+                               []
+                       ),
+                       'htmlTagAlsoFindsIdentifiers' => array(
+                               ['f', 'xyz'],
+                               '<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                               xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">
+
+                                       Content
+                               </html>',
+                               []
+                       ),
+                       'htmlTagWithNamespaceTypo3FluidAttributeTagAlsoFindsIdentifiers' => array(
+                               ['f', 'xyz'],
+                               '<html data-namespace-typo3-fluid="true"
+                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                       xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">
+
+                                       Content
+                               </html>',
+                               []
+                       ),
+                       'nonHtmlTagAlsoFindsIdentifiers' => array(
+                               ['f', 'xyz'],
+                               '<typo3-root
+                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                       xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">
+
+                                       Content
+                               </typo3-root>',
+                               []
+                       ),
+               ];
+       }
+
+       /**
+        * @param string $expectedOut
+        * @param string $templateString
+        * @param array $foundIdentifiers
+        * @test
+        * @dataProvider removeXmlnsViewHelperNamespaceDeclarationsDataProvider
+        */
+       public function removeXmlnsViewHelperNamespaceDeclarationsWorks($expectedOut, array $foundIdentifiers, $templateString) {
+               $templateParser = $this->getAccessibleMock(TemplateParser::class, array('dummy'));
+               $templateString = $templateParser->_call('removeXmlnsViewHelperNamespaceDeclarations', $templateString, $foundIdentifiers);
+
+               // remove tabs and trim because expected result and given have a different tab count in dataProvider which is not relevant for the parser (xml and html)
+               $this->assertSame(trim(str_replace("\t", '', $expectedOut)), trim(str_replace("\t", '', $templateString)));
+       }
+
+       /**
+        * DataProvider for removeXmlnsViewHelperNamespaceDeclarationsWorks test
+        *
+        * @return array
+        */
+       public function removeXmlnsViewHelperNamespaceDeclarationsDataProvider() {
+               return [
+                       'onlyViewHelperXmlns' => array(
+                               '
+                                       <div >
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'fe'],
+                               '<div xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers">
+                                       <f:if condition="{demo}">Hello World</f:if>
+                               </div>'
+                       ),
+                       'xmlnsViewHelpersFoundWithNonViewHelperXmlnsAtBeginning' => array(
+                               '
+                                       <div xmlns:z="http://www.typo3.org/foo" >
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'fe'],
+                               '
+                                       <div xmlns:z="http://www.typo3.org/foo"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'xmlnsViewHelpersFoundWithNonViewHelperXmlnsAtEnd' => array(
+                               '
+                                       <div xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'fe'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'xmlnsViewHelpersFoundWithMultipleNonViewHelperXmlns' => array(
+                               '
+                                       <div xmlns:y="http://www.typo3.org/bar" xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'fe'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:y="http://www.typo3.org/bar"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'xmlnsViewHelpersFoundWithNonViewHelperXmlnsBetween' => array(
+                               '
+                                       <div xmlns:z="http://www.typo3.org/foo" >
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['fe', 'f'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'removeHtmlTagWithAttributeButNoXmlnsViewHelpersFound' => array(
+                               '<f:if condition="{demo}">Hello World</f:if>',
+                               [],
+                               '
+                                       <html data-namespace-typo3-fluid="true">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               '
+                       ),
+                       'doNotRemoveHtmlTagBecauseHtmlTagNotMarkedAsFluidNamespaceDefinitionTag' => array(
+                               '
+                                       <html xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               ',
+                               ['fe', 'f'],
+                               '
+                                       <html xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               '
+                       ),
+                       'doNotModifyHtmlTagBecauseViewHelperXmlnsNotFoundInTagAndNotMarkedForRemoval' => array(
+                               '
+                                       <html xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               ',
+                               ['f'], // required because without any found namespaces the method will not do any replacements
+                               '
+                                       <html xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               '
+                       ),
+                       'removeHtmlTagBecauseXmlnsFoundInTagAndMarkedAsFluidViewHelperDefinitionTag' => array(
+                               '<f:if condition="{demo}">Hello World</f:if>',
+                               ['fe'],
+                               '
+                                       <html data-namespace-typo3-fluid="true"
+                                                       xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               '
+                       ),
+                       'removeHtmlTagBecauseXmlnsFoundInDifferentTagAndMarkedAsFluidViewHelperDefinitionTag' => array(
+                               '<f:if condition="{demo}">Hello World</f:if>',
+                               ['f'],
+                               '
+                                       <html data-namespace-typo3-fluid="true" xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </html>
+                               '
+                       ),
+                       'producesExcpedtedOutputIfFouundIdentifiersAreWrongButContainNoExistingNonViewHelperXmlns' => array(
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers" xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'i'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       // this test verifies that the expected output can be wrong if the foundNameSpaces are incorrect
+                       // which is why extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiers
+                       // tests if the correct identifiers are found
+                       'removesNonViewHelperNamespaceIfFoundIdentifiersAreWrong' => array(
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers" >
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'z'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       // this verifies that the scan pattern was correctly quoted for the regular expression
+                       // because if the regular expression delimiter were to be modified in the pattern,
+                       // the corresponding preg_quote will fail without adaptions
+                       'xmlnsWithScanPatternAsIdentifier' => array(
+                               '
+                                       <div >
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               [TemplateParser::$SCAN_PATTERN_REMOVE_VIEWHELPERS_XMLNSDECLARATIONS],
+                               '
+                                       <div xmlns:' . TemplateParser::$SCAN_PATTERN_REMOVE_VIEWHELPERS_XMLNSDECLARATIONS . '="http://typo3.org/ns/TYPO3/CMS\Demo/ViewHelpers">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       // these scenarios also need to because even if the foundIdentifiers are
+                       // invalid the method should still work as expected,
+                       // Furthermore, currently these patterns are allowed for foundIdentifiers
+                       // see also test extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiers
+                       'xmlnsIdentifiersWithWhitespaces' => array(
+                               '
+                                       <div xmlns:none xyz="http://domain.tld/ns/NoneXyz/viewhelpers" >
+
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               [' ', 'foo bar', '"x y z"'],
+                               '
+                                       <div xmlns: ="http://typo3.org/ns/Some/Package/ViewHelpers"
+                                                       xmlns:foo bar="http://domain.tld/ns/foobar/viewhelpers"
+                                                       xmlns:none xyz="http://domain.tld/ns/NoneXyz/viewhelpers"
+                                                       xmlns:"x y z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
+
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'xmlnsWithRegularExpressionAsIdentifier' => array(
+                               '
+                                       <div xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'fe', '.*.?\\s'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:.*.?\\s="http://typo3.org/ns/TYPO3/CMS\Demo/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'xmlnsWithRegularExpressionDelimiterAsIdentifier' => array(
+                               '
+                                       <div xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['f', 'fe', '/'],
+                               '
+                                       <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
+                                                       xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+                                                       xmlns:/="http://typo3.org/ns/TYPO3/CMS\Demo/ViewHelpers"
+                                                       xmlns:z="http://www.typo3.org/foo">
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       ),
+                       'xmlnsWithEqualsSign' => array(
+                               '
+                                       <div xmlns:none=xyz="http://domain.tld/ns/NoneXyz/viewhelpers" >
+
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               ',
+                               ['=', 'foo=bar', '"x=y=z"'],
+                               '
+                                       <div xmlns:=="http://typo3.org/ns/Some/Package/ViewHelpers"
+                                                       xmlns:foo=bar="http://domain.tld/ns/foobar/viewhelpers"
+                                                       xmlns:none=xyz="http://domain.tld/ns/NoneXyz/viewhelpers"
+                                                       xmlns:"x=y=z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
+
+                                               <f:if condition="{demo}">Hello World</f:if>
+                                       </div>
+                               '
+                       )
+               ];
+       }
+
+       /**
         * @test
         */
        public function viewHelperNameWithMultipleLevelsCanBeResolvedByResolveViewHelperName() {