From 0128747c6cc2882b7b694d8b16424ac33fa0b1a9 Mon Sep 17 00:00:00 2001 From: Frederik Bosch Date: Fri, 11 Aug 2023 12:41:49 +0200 Subject: [PATCH] fix output of namespaces when using xsl:copy-of in a xsl:for-each-group statement --- src/Callback/FunctionCollection.php | 2 +- src/Xpath/Compiler.php | 4 ++-- src/Xpath/Expression/DoubleQuoteExpression.php | 2 +- src/Xpath/Expression/ForLoopExpression.php | 2 +- src/Xpath/Expression/FunctionExpression.php | 10 +++++----- src/Xpath/Expression/SequenceExpression.php | 2 +- src/Xpath/ExpressionInterface.php | 2 +- src/Xsl/Functions/GroupBy.php | 6 +----- test/Integration/Xsl/ForEachGroupTest.php | 14 ++++++++++++++ .../group-by-namespace-functions-copy-of.xsl | 17 +++++++++++++++++ test/Stubs/packages.xml | 4 ++++ 11 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 test/Stubs/Xsl/ForEachGroup/group-by-namespace-functions-copy-of.xsl diff --git a/src/Callback/FunctionCollection.php b/src/Callback/FunctionCollection.php index 0d591c1..fb5ebd6 100644 --- a/src/Callback/FunctionCollection.php +++ b/src/Callback/FunctionCollection.php @@ -8,7 +8,7 @@ final class FunctionCollection /** * @var array */ - private $collection = []; + public $collection = []; /** * @param string $namespace diff --git a/src/Xpath/Compiler.php b/src/Xpath/Compiler.php index ff65834..a6f17a2 100644 --- a/src/Xpath/Compiler.php +++ b/src/Xpath/Compiler.php @@ -57,13 +57,13 @@ public function compile(string $xpathExpression, DOMNode $currentElement): strin * @param DOMNode $currentElement * @return string */ - public function compileTokens(Lexer $tokens, DOMNode $currentElement): string + public function compileTokens(Lexer $tokens, DOMNode $currentElement, array $namespaces = []): string { $resultTokens = []; foreach ($tokens as $token) { foreach ($this->expressions as $expression) { if ($expression->supports($tokens)) { - $resultTokens = $expression->merge($tokens, $currentElement, $resultTokens); + $resultTokens = $expression->merge($tokens, $currentElement, $resultTokens, $namespaces); continue 2; } } diff --git a/src/Xpath/Expression/DoubleQuoteExpression.php b/src/Xpath/Expression/DoubleQuoteExpression.php index ea2f5f4..589b97a 100644 --- a/src/Xpath/Expression/DoubleQuoteExpression.php +++ b/src/Xpath/Expression/DoubleQuoteExpression.php @@ -31,7 +31,7 @@ public function supports(Lexer $lexer): bool * @param array $tokens * @return array */ - public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens): array + public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens, array $namespaces = []): array { $expression = $lexer->current(); diff --git a/src/Xpath/Expression/ForLoopExpression.php b/src/Xpath/Expression/ForLoopExpression.php index 8c02966..043d240 100644 --- a/src/Xpath/Expression/ForLoopExpression.php +++ b/src/Xpath/Expression/ForLoopExpression.php @@ -35,7 +35,7 @@ public function supports(Lexer $lexer): bool * @param array $tokens * @return array */ - public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens): array + public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens, array $namespaces = []): array { \array_splice( $tokens, diff --git a/src/Xpath/Expression/FunctionExpression.php b/src/Xpath/Expression/FunctionExpression.php index 29a4e86..0555725 100644 --- a/src/Xpath/Expression/FunctionExpression.php +++ b/src/Xpath/Expression/FunctionExpression.php @@ -41,9 +41,9 @@ public function supports(Lexer $lexer): bool * @param array $tokens * @return array */ - public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens): array + public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens, array $namespaces = []): array { - return \array_merge($tokens, $this->createFunctionTokens($lexer, $currentElement)); + return \array_merge($tokens, $this->createFunctionTokens($lexer, $currentElement, $namespaces)); } /** @@ -51,7 +51,7 @@ public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens): arr * @param DOMNode $currentElement * @return string[] */ - private function createFunctionTokens(Lexer $lexer, DOMNode $currentElement) + private function createFunctionTokens(Lexer $lexer, DOMNode $currentElement, array $namespaces = []) { if ($currentElement->ownerDocument instanceof DOMDocument === false) { throw new \UnexpectedValueException('Expecting currentElement attached to document'); @@ -59,8 +59,8 @@ private function createFunctionTokens(Lexer $lexer, DOMNode $currentElement) $token = $lexer->current(); $documentElement = $currentElement->ownerDocument->documentElement; - $namespaces = FetchNamespacesFromNode::fetch($documentElement); - $functionQname = $this->convertTokenToFunctionName($token, $namespaces); + $documentNamespaces = \array_merge(FetchNamespacesFromNode::fetch($documentElement), $namespaces); + $functionQname = $this->convertTokenToFunctionName($token, $documentNamespaces); try { $dot = \strrpos($functionQname, ':'); diff --git a/src/Xpath/Expression/SequenceExpression.php b/src/Xpath/Expression/SequenceExpression.php index b2c9e3e..d4ae69a 100644 --- a/src/Xpath/Expression/SequenceExpression.php +++ b/src/Xpath/Expression/SequenceExpression.php @@ -78,7 +78,7 @@ public function supports(Lexer $lexer): bool * @param array $tokens * @return array */ - public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens): array + public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens, array $namespaces = []): array { return \array_merge($tokens, $this->sequenceConstructor->serialize($lexer, $currentElement)); } diff --git a/src/Xpath/ExpressionInterface.php b/src/Xpath/ExpressionInterface.php index ef9386b..e8b025d 100644 --- a/src/Xpath/ExpressionInterface.php +++ b/src/Xpath/ExpressionInterface.php @@ -19,5 +19,5 @@ public function supports(Lexer $lexer): bool; * @param array $tokens * @return array */ - public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens): array; + public function merge(Lexer $lexer, DOMNode $currentElement, array $tokens, array $namespaces = []): array; } diff --git a/src/Xsl/Functions/GroupBy.php b/src/Xsl/Functions/GroupBy.php index b320317..687d094 100644 --- a/src/Xsl/Functions/GroupBy.php +++ b/src/Xsl/Functions/GroupBy.php @@ -25,12 +25,8 @@ public static function distinct(Arguments $arguments, TransformationContext $con /** @var DOMElement $current */ $current = $arguments->get(3)[0]; - foreach ($namespaces as $prefix => $namespace) { - $current->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $prefix, $namespace); - } - $compiler = new Compiler($context->getFunctions()); - $xpathExpression = $compiler->compileTokens(Lexer::tokenize('string(' . $groupBy . ')'), $current); + $xpathExpression = $compiler->compileTokens(Lexer::tokenize('string(' . $groupBy . ')'), $current, $namespaces); $values = []; foreach ($list as $key => $element) { diff --git a/test/Integration/Xsl/ForEachGroupTest.php b/test/Integration/Xsl/ForEachGroupTest.php index 56a8c1b..3e10f22 100644 --- a/test/Integration/Xsl/ForEachGroupTest.php +++ b/test/Integration/Xsl/ForEachGroupTest.php @@ -206,6 +206,20 @@ public function testWithNamespaceFunctions(): void $this->assertEquals('201120152014', \trim($processor->transformToXml($data))); } + public function testWithNamespaceFunctionsCopyOf(): void + { + $styleSheet = new DOMDocument(); + $styleSheet->load('Stubs/Xsl/ForEachGroup/group-by-namespace-functions-copy-of.xsl'); + + $processor = new XsltProcessor(new NullCache()); + $processor->importStyleSheet($styleSheet); + + $data = new DOMDocument(); + $data->load('Stubs/packages.xml'); + + $this->assertEquals('

test

test

test

test

', \trim($processor->transformToXml($data))); + } + public function testByAttributeValueTemplates(): void { $styleSheet = new DOMDocument(); diff --git a/test/Stubs/Xsl/ForEachGroup/group-by-namespace-functions-copy-of.xsl b/test/Stubs/Xsl/ForEachGroup/group-by-namespace-functions-copy-of.xsl new file mode 100644 index 0000000..b8bf3d2 --- /dev/null +++ b/test/Stubs/Xsl/ForEachGroup/group-by-namespace-functions-copy-of.xsl @@ -0,0 +1,17 @@ + + + + + + + + +
+
+
+ +
+ +
\ No newline at end of file diff --git a/test/Stubs/packages.xml b/test/Stubs/packages.xml index cd39f6f..7b81b63 100644 --- a/test/Stubs/packages.xml +++ b/test/Stubs/packages.xml @@ -7,6 +7,7 @@ +

test

Genkgo @@ -16,6 +17,7 @@ +

test

Genkgo @@ -25,6 +27,7 @@ +

test

Genkgo @@ -34,5 +37,6 @@ +

test