You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mu...@apache.org on 2023/07/07 11:47:15 UTC
[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 'if' conditional expression, and few related new working test cases
This is an automated email from the ASF dual-hosted git repository.
mukulg pushed a commit to branch xalan-j_xslt3.0
in repository https://gitbox.apache.org/repos/asf/xalan-java.git
The following commit(s) were added to refs/heads/xalan-j_xslt3.0 by this push:
new 1d55a98f committing implementation of xpath 3.1 'if' conditional expression, and few related new working test cases
new f8483e13 Merge pull request #21 from mukulga/xalan-j_xslt3.0_mukul
1d55a98f is described below
commit 1d55a98f4daad55e8053de710ec481552dd8ffd2
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Fri Jul 7 17:10:12 2023 +0530
committing implementation of xpath 3.1 'if' conditional expression, and few related new working test cases
---
src/org/apache/xpath/compiler/Compiler.java | 7 ++
src/org/apache/xpath/compiler/OpCodes.java | 4 +-
src/org/apache/xpath/compiler/XPathParser.java | 105 +++++++++++++++---
src/org/apache/xpath/composite/IfExpr.java | 142 +++++++++++++++++++++++++
tests/if_expr/gold/test1.out | 1 +
tests/if_expr/gold/test2.out | 1 +
tests/if_expr/gold/test3.out | 10 ++
tests/if_expr/gold/test4.out | 26 +++++
tests/if_expr/gold/test5.out | 6 ++
tests/if_expr/gold/test6.out | 14 +++
tests/if_expr/test1.xsl | 37 +++++++
tests/if_expr/test1_a.xml | 5 +
tests/if_expr/test1_b.xml | 5 +
tests/if_expr/test1_c.xml | 23 ++++
tests/if_expr/test1_d.xml | 11 ++
tests/if_expr/test1_e.xml | 21 ++++
tests/if_expr/test2.xsl | 38 +++++++
tests/if_expr/test3.xsl | 49 +++++++++
tests/if_expr/test4.xsl | 46 ++++++++
tests/if_expr/test5.xsl | 56 ++++++++++
tests/org/apache/xalan/xpath3/IfExprTests.java | 110 +++++++++++++++++++
tests/org/apache/xalan/xslt3/AllXsl3Tests.java | 3 +-
22 files changed, 706 insertions(+), 14 deletions(-)
diff --git a/src/org/apache/xpath/compiler/Compiler.java b/src/org/apache/xpath/compiler/Compiler.java
index 1ee1b6d0..b67d3c51 100644
--- a/src/org/apache/xpath/compiler/Compiler.java
+++ b/src/org/apache/xpath/compiler/Compiler.java
@@ -129,6 +129,8 @@ public class Compiler extends OpMap
{
case OpCodes.OP_XPATH :
expr = compile(opPos + 2); break;
+ case OpCodes.OP_IF_EXPR :
+ expr = ifExpr(opPos); break;
case OpCodes.OP_OR :
expr = or(opPos); break;
case OpCodes.OP_AND :
@@ -1170,6 +1172,11 @@ private static final boolean DEBUG = false;
{
return XPathParser.fDynamicFunctionCall;
}
+
+ Expression ifExpr(int opPos) throws TransformerException
+ {
+ return XPathParser.fIfExpr;
+ }
// The current id for extension functions.
private static long s_nextMethodId = 0;
diff --git a/src/org/apache/xpath/compiler/OpCodes.java b/src/org/apache/xpath/compiler/OpCodes.java
index bdf4a5db..92fb38f5 100644
--- a/src/org/apache/xpath/compiler/OpCodes.java
+++ b/src/org/apache/xpath/compiler/OpCodes.java
@@ -679,8 +679,10 @@ public class OpCodes
public static final int OP_INLINE_FUNCTION = 61;
public static final int OP_DYNAMIC_FUNCTION_CALL = 62;
+
+ public static final int OP_IF_EXPR = 63;
/** The next free ID. Please keep this up to date. */
- private static final int NEXT_FREE_ID = 63;
+ private static final int NEXT_FREE_ID = 64;
}
diff --git a/src/org/apache/xpath/compiler/XPathParser.java b/src/org/apache/xpath/compiler/XPathParser.java
index a833379f..c5493cf6 100644
--- a/src/org/apache/xpath/compiler/XPathParser.java
+++ b/src/org/apache/xpath/compiler/XPathParser.java
@@ -30,6 +30,7 @@ import javax.xml.transform.TransformerException;
import org.apache.xalan.res.XSLMessages;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xpath.XPathProcessorException;
+import org.apache.xpath.composite.IfExpr;
import org.apache.xpath.domapi.XPathStylesheetDOM3Exception;
import org.apache.xpath.functions.DynamicFunctionCall;
import org.apache.xpath.objects.InlineFunction;
@@ -79,19 +80,23 @@ public class XPathParser
protected final static int FILTER_MATCH_PREDICATES = 2;
/*
- * While parsing XPath 3.1 "function item" inline function expressions and,
- * dynamic function calls, we use this constant string array to make parse
- * decisions. The elements of this array are certain XPath operator names
- * that need this support.
+ * While parsing certain XPath 3.1 expressions, we use this constant string
+ * array to make parse decisions. The elements of this array are certain
+ * XPath 'operator names' and 'key words' that need this support.
*/
private static final String[] XPATH_OP_ARR = new String[] {"div", "or", "and", "mod", "to",
- "eq", "ne", "lt", "gt", "le", "ge"};
+ "eq", "ne", "lt", "gt", "le", "ge",
+ "if", "then", "else"};
private List<String> fXpathOpArrTokensList = null;
static InlineFunction fInlineFunction = null;
static DynamicFunctionCall fDynamicFunctionCall = null;
+
+ static IfExpr fIfExpr = null;
+
+ private boolean fIsXpathPredicateParsingActive = false;
/**
* The parser constructor.
@@ -599,7 +604,8 @@ public class XPathParser
if ("$".equals(funcBodyXPathExprStrPartsArr[idx]) && (idx <
(funcBodyXPathExprStrPartsArr.length - 1))) {
- // this handles, variable references within XPath expression inline function's body
+ // this handles, variable references within XPath expression string
+ // that's been formed within this method.
xpathExprStrPart = "$" + funcBodyXPathExprStrPartsArr[idx + 1];
idx += 1;
}
@@ -831,14 +837,86 @@ public class XPathParser
/**
*
*
- * Expr ::= OrExpr
- *
+ * Expr ::= IfExpr
+ * | OrExpr
*
* @throws javax.xml.transform.TransformerException
*/
protected void Expr() throws javax.xml.transform.TransformerException
{
- OrExpr();
+ if (tokenIs("if")) {
+ fIfExpr = IfExpr();
+ }
+ else {
+ OrExpr();
+ }
+ }
+
+ protected IfExpr IfExpr() throws javax.xml.transform.TransformerException
+ {
+ int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
+
+ nextToken();
+
+ insertOp(opPos, 2, OpCodes.OP_IF_EXPR);
+
+ IfExpr ifExpr = new IfExpr();
+
+ consumeExpected('(');
+
+ List<String> conditionalExprXPathStrPartsList = new ArrayList<String>();
+
+ while (!tokenIs("then") && m_token != null)
+ {
+ conditionalExprXPathStrPartsList.add(m_token);
+ nextToken();
+ }
+
+ consumeExpected("then");
+
+ conditionalExprXPathStrPartsList = conditionalExprXPathStrPartsList.subList(0,
+ conditionalExprXPathStrPartsList.size() - 1);
+
+ String conditionalXPathExprStr = getXPathStrFromComponentParts(conditionalExprXPathStrPartsList);
+
+ List<String> thenExprXPathStrPartsList = new ArrayList<String>();
+
+ while (!tokenIs("else") && m_token != null)
+ {
+ thenExprXPathStrPartsList.add(m_token);
+ nextToken();
+ }
+
+ consumeExpected("else");
+
+ String thenXPathExprStr = getXPathStrFromComponentParts(thenExprXPathStrPartsList);
+
+ List<String> elseExprXPathStrPartsList = new ArrayList<String>();
+
+ while (m_token != null)
+ {
+ if (fIsXpathPredicateParsingActive && lookahead(']', 1)) {
+ elseExprXPathStrPartsList.add(m_token);
+ elseExprXPathStrPartsList.subList(0, elseExprXPathStrPartsList.size() - 1);
+ nextToken();
+ break;
+ }
+ else {
+ elseExprXPathStrPartsList.add(m_token);
+ nextToken();
+ }
+ }
+
+ String elseXPathExprStr = getXPathStrFromComponentParts(elseExprXPathStrPartsList);
+
+ ifExpr.setConditionalExprXPathStr(conditionalXPathExprStr);
+ ifExpr.setThenExprXPathStr(thenXPathExprStr);
+ ifExpr.setElseExprXPathStr(elseXPathExprStr);
+
+ m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
+ m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
+
+ return ifExpr;
}
/**
@@ -1548,7 +1626,7 @@ public class XPathParser
* | FunctionCall
* | FunctionItemExpr
*
- * The XPath grammar option 'VarRef ArgumentList' shown above
+ * The XPath grammar option 'VarRef ArgumentList' mentioned above
* denotes, dynamic function call.
*
* @return true if this method successfully matched a PrimaryExpr
@@ -2239,9 +2317,12 @@ public class XPathParser
if (tokenIs('['))
{
+ fIsXpathPredicateParsingActive = true;
+
nextToken();
- PredicateExpr();
- consumeExpected(']');
+ PredicateExpr();
+ fIsXpathPredicateParsingActive = false;
+ consumeExpected(']');
}
}
diff --git a/src/org/apache/xpath/composite/IfExpr.java b/src/org/apache/xpath/composite/IfExpr.java
new file mode 100644
index 00000000..e5364d94
--- /dev/null
+++ b/src/org/apache/xpath/composite/IfExpr.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xpath.composite;
+
+import java.util.Vector;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xpath.Expression;
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.XPathVisitor;
+import org.apache.xpath.objects.XObject;
+
+/*
+ * The XalanJ xpath parser, creates and populates an object of this class,
+ * as a representation of XPath 3.1 "if" conditional expressions.
+ *
+ * XPath 3.1 spec, provides following definitions of conditional expressions.
+ *
+ * Grammar fragment,
+ * IfExpr ::= "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
+ *
+ * The expression following the if keyword is called the test expression, and
+ * the expressions following the then and else keywords are called the
+ * then-expression and else-expression, respectively.
+ *
+ * The first step in processing a conditional expression is to find the
+ * effective boolean value of the test expression.
+ *
+ * The value of a conditional expression is defined as follows: If the
+ * effective boolean value of the test expression is true, the value of
+ * the then-expression is returned. If the effective boolean value of the
+ * test expression is false, the value of the else-expression is returned.
+ *
+ * @author Mukul Gandhi <mu...@apache.org>
+ *
+ * @xsl.usage advanced
+ */
+public class IfExpr extends Expression {
+
+ private static final long serialVersionUID = 4057572946055830336L;
+
+ private String conditionalExprXPathStr;
+
+ private String thenExprXPathStr;
+
+ private String elseExprXPathStr;
+
+ // the following two fields of this class, are used during
+ // XPath.fixupVariables(..) action as performed within object of
+ // this class.
+ private Vector fVars;
+ private int fGlobalsSize;
+
+ public String getConditionalExprXPathStr() {
+ return conditionalExprXPathStr;
+ }
+
+ public void setConditionalExprXPathStr(String conditionalExprXPathStr) {
+ this.conditionalExprXPathStr = conditionalExprXPathStr;
+ }
+
+ public String getThenExprXPathStr() {
+ return thenExprXPathStr;
+ }
+
+ public void setThenExprXPathStr(String thenExprXPathStr) {
+ this.thenExprXPathStr = thenExprXPathStr;
+ }
+
+ public String getElseExprXPathStr() {
+ return elseExprXPathStr;
+ }
+
+ public void setElseExprXPathStr(String elseExprXPathStr) {
+ this.elseExprXPathStr = elseExprXPathStr;
+ }
+
+ @Override
+ public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) {
+ // no op
+ }
+
+ @Override
+ public XObject execute(XPathContext xctxt) throws TransformerException {
+ XObject evalResult = null;
+
+ SourceLocator srcLocator = xctxt.getSAXLocator();
+
+ int contextNode = xctxt.getContextNode();
+
+ XPath conditionlExprXpath = new XPath(conditionalExprXPathStr, srcLocator, null,
+ XPath.SELECT, null);
+ conditionlExprXpath.fixupVariables(fVars, fGlobalsSize);
+
+ XObject conditionalXpathExprResult = conditionlExprXpath.execute(xctxt, contextNode, null);
+
+ if (conditionalXpathExprResult.bool()) {
+ XPath thenExprXpath = new XPath(thenExprXPathStr, srcLocator, null, XPath.SELECT, null);
+ thenExprXpath.fixupVariables(fVars, fGlobalsSize);
+
+ evalResult = thenExprXpath.execute(xctxt, contextNode, null);
+ }
+ else {
+ XPath elseExprXpath = new XPath(elseExprXPathStr, srcLocator, null, XPath.SELECT, null);
+ elseExprXpath.fixupVariables(fVars, fGlobalsSize);
+
+ evalResult = elseExprXpath.execute(xctxt, contextNode, null);
+ }
+
+ return evalResult;
+ }
+
+ @Override
+ public void fixupVariables(Vector vars, int globalsSize) {
+ fVars = (Vector)(vars.clone());
+ fGlobalsSize = globalsSize;
+ }
+
+ @Override
+ public boolean deepEquals(Expression expr) {
+ return false;
+ }
+
+}
diff --git a/tests/if_expr/gold/test1.out b/tests/if_expr/gold/test1.out
new file mode 100644
index 00000000..c46008d2
--- /dev/null
+++ b/tests/if_expr/gold/test1.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>x is less than y</result>
diff --git a/tests/if_expr/gold/test2.out b/tests/if_expr/gold/test2.out
new file mode 100644
index 00000000..9229ad61
--- /dev/null
+++ b/tests/if_expr/gold/test2.out
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><result>x is greater or equal to y</result>
diff --git a/tests/if_expr/gold/test3.out b/tests/if_expr/gold/test3.out
new file mode 100644
index 00000000..45d82e28
--- /dev/null
+++ b/tests/if_expr/gold/test3.out
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <item>
+ <a>7</a>
+ <b>2</b>
+ </item>
+ <item>
+ <a>8</a>
+ <b>2</b>
+ </item>
+</result>
diff --git a/tests/if_expr/gold/test4.out b/tests/if_expr/gold/test4.out
new file mode 100644
index 00000000..ebc30932
--- /dev/null
+++ b/tests/if_expr/gold/test4.out
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <lessOrEqual count="3">
+ <item>
+ <a>1</a>
+ <b>3</b>
+ </item>
+ <item>
+ <a>2</a>
+ <b>5</b>
+ </item>
+ <item>
+ <a>4</a>
+ <b>12</b>
+ </item>
+ </lessOrEqual>
+ <greater count="2">
+ <item>
+ <a>7</a>
+ <b>2</b>
+ </item>
+ <item>
+ <a>8</a>
+ <b>2</b>
+ </item>
+ </greater>
+</result>
diff --git a/tests/if_expr/gold/test5.out b/tests/if_expr/gold/test5.out
new file mode 100644
index 00000000..6af91649
--- /dev/null
+++ b/tests/if_expr/gold/test5.out
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <widget>
+ <name>abc</name>
+ <unit-cost>7</unit-cost>
+ </widget>
+</result>
diff --git a/tests/if_expr/gold/test6.out b/tests/if_expr/gold/test6.out
new file mode 100644
index 00000000..b8a33306
--- /dev/null
+++ b/tests/if_expr/gold/test6.out
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+ <part>
+ <name>part1</name>
+ <wholesale>
+ <price>5</price>
+ </wholesale>
+ </part>
+ <part>
+ <name>part2</name>
+ <retail>
+ <price>15</price>
+ </retail>
+ </part>
+</result>
diff --git a/tests/if_expr/test1.xsl b/tests/if_expr/test1.xsl
new file mode 100644
index 00000000..7e6941e8
--- /dev/null
+++ b/tests/if_expr/test1.xsl
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_a.xml, test1_b.xml -->
+
+ <!-- An XSLT stylesheet, to test "if" conditional expression. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/elem">
+ <result>
+ <xsl:value-of select="if (x lt y) then ('x is less than y') else ('x is greater or equal to y')"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/if_expr/test1_a.xml b/tests/if_expr/test1_a.xml
new file mode 100644
index 00000000..c67c2ed4
--- /dev/null
+++ b/tests/if_expr/test1_a.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+ <x>3</x>
+ <y>7</y>
+</elem>
\ No newline at end of file
diff --git a/tests/if_expr/test1_b.xml b/tests/if_expr/test1_b.xml
new file mode 100644
index 00000000..64985618
--- /dev/null
+++ b/tests/if_expr/test1_b.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+ <x>7</x>
+ <y>3</y>
+</elem>
\ No newline at end of file
diff --git a/tests/if_expr/test1_c.xml b/tests/if_expr/test1_c.xml
new file mode 100644
index 00000000..c6e81550
--- /dev/null
+++ b/tests/if_expr/test1_c.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<elem>
+ <item>
+ <a>1</a>
+ <b>3</b>
+ </item>
+ <item>
+ <a>2</a>
+ <b>5</b>
+ </item>
+ <item>
+ <a>7</a>
+ <b>2</b>
+ </item>
+ <item>
+ <a>8</a>
+ <b>2</b>
+ </item>
+ <item>
+ <a>4</a>
+ <b>12</b>
+ </item>
+</elem>
\ No newline at end of file
diff --git a/tests/if_expr/test1_d.xml b/tests/if_expr/test1_d.xml
new file mode 100644
index 00000000..cec0a65b
--- /dev/null
+++ b/tests/if_expr/test1_d.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widgets>
+ <widget>
+ <name>abc</name>
+ <unit-cost>7</unit-cost>
+ </widget>
+ <widget>
+ <name>pqr</name>
+ <unit-cost>10</unit-cost>
+ </widget>
+</widgets>
\ No newline at end of file
diff --git a/tests/if_expr/test1_e.xml b/tests/if_expr/test1_e.xml
new file mode 100644
index 00000000..ee9110e6
--- /dev/null
+++ b/tests/if_expr/test1_e.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<parts>
+ <part discounted="part_is_discounted">
+ <name>part1</name>
+ <wholesale>
+ <price>5</price>
+ </wholesale>
+ <retail>
+ <price>7</price>
+ </retail>
+ </part>
+ <part>
+ <name>part2</name>
+ <wholesale>
+ <price>12</price>
+ </wholesale>
+ <retail>
+ <price>15</price>
+ </retail>
+ </part>
+</parts>
\ No newline at end of file
diff --git a/tests/if_expr/test2.xsl b/tests/if_expr/test2.xsl
new file mode 100644
index 00000000..0fd90efa
--- /dev/null
+++ b/tests/if_expr/test2.xsl
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_c.xml -->
+
+ <!-- An XSLT stylesheet, to test "if" conditional expression
+ that exists within an XPath predicate. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/elem">
+ <result>
+ <xsl:copy-of select="item[if (number(a) gt number(b)) then true() else false()]"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/if_expr/test3.xsl b/tests/if_expr/test3.xsl
new file mode 100644
index 00000000..ec49a577
--- /dev/null
+++ b/tests/if_expr/test3.xsl
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_c.xml -->
+
+ <!-- An XSLT stylesheet, to test the XPath 3.1 "if" conditional
+ expression, when used within xsl:for-each-group to transform
+ the current-grouping-key() value. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:variable name="gThan" select="function($x, $y) { $x gt $y }"/>
+
+ <xsl:template match="/elem">
+ <result>
+ <xsl:for-each-group select="item" group-by="$gThan(a, b)">
+ <xsl:variable name="grtOrLess" select="if (string(current-grouping-key()) eq 'true')
+ then 'greater'
+ else 'lessOrEqual'"/>
+ <xsl:element name="{normalize-space($grtOrLess)}">
+ <xsl:attribute name="count" select="count(current-group())"/>
+ <xsl:copy-of select="current-group()"/>
+ </xsl:element>
+ </xsl:for-each-group>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/if_expr/test4.xsl b/tests/if_expr/test4.xsl
new file mode 100644
index 00000000..9218bffc
--- /dev/null
+++ b/tests/if_expr/test4.xsl
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_d.xml -->
+
+ <!-- An XSLT stylesheet, to test the XPath 3.1 "if" conditional
+ expression. The XPath "if" conditional expression example
+ illustrated within this stylesheet test, is borrowed from
+ XPath 3.1 spec, with minor modifications. This stylesheet
+ example uses the fn:number function, but XPath 3.1 spec
+ doesn't. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/widgets">
+ <result>
+ <xsl:variable name="widget1" select="widget[1]"/>
+ <xsl:variable name="widget2" select="widget[2]"/>
+ <xsl:copy-of select="if (number($widget1/unit-cost) < number($widget2/unit-cost))
+ then $widget1
+ else $widget2"/>
+ </result>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/if_expr/test5.xsl b/tests/if_expr/test5.xsl
new file mode 100644
index 00000000..4954d9f6
--- /dev/null
+++ b/tests/if_expr/test5.xsl
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- use with test1_e.xml -->
+
+ <!-- An XSLT stylesheet, to test the XPath 3.1 "if" conditional
+ expression. The XPath "if" conditional expression example
+ illustrated within this stylesheet test, is borrowed from
+ XPath 3.1 spec. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/parts">
+ <result>
+ <xsl:call-template name="analyzePart">
+ <xsl:with-param name="part" select="part[1]"/>
+ </xsl:call-template>
+ <xsl:call-template name="analyzePart">
+ <xsl:with-param name="part" select="part[2]"/>
+ </xsl:call-template>
+ </result>
+ </xsl:template>
+
+ <xsl:template name="analyzePart">
+ <xsl:param name="part"/>
+
+ <part>
+ <xsl:copy-of select="$part/name"/>
+ <xsl:copy-of select="if ($part/@discounted)
+ then $part/wholesale
+ else $part/retail"/>
+ </part>
+ </xsl:template>
+
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/tests/org/apache/xalan/xpath3/IfExprTests.java b/tests/org/apache/xalan/xpath3/IfExprTests.java
new file mode 100644
index 00000000..4e422b93
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/IfExprTests.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xalan.xpath3;
+
+import org.apache.xalan.util.XslTransformTestsUtil;
+import org.apache.xalan.xslt3.XSLConstants;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * XPath 3.1 test cases, for "if" conditional expressions.
+ *
+ * @author Mukul Gandhi <mu...@apache.org>
+ *
+ * @xsl.usage advanced
+ */
+public class IfExprTests extends XslTransformTestsUtil {
+
+ private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + "if_expr/";
+
+ private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + "if_expr/gold/";
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ // no op
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ xmlDocumentBuilderFactory = null;
+ xmlDocumentBuilder = null;
+ xslTransformerFactory = null;
+ }
+
+ @Test
+ public void xslIfExprTest1() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test1.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslIfExprTest2() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test2.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslIfExprTest3() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_c.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test2.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test3.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslIfExprTest4() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_c.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test4.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslIfExprTest5() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_d.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test4.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test5.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+ @Test
+ public void xslIfExprTest6() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_e.xml";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test5.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test6.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
+
+}
diff --git a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
index 0aae607c..e5176c6b 100644
--- a/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
+++ b/tests/org/apache/xalan/xslt3/AllXsl3Tests.java
@@ -24,6 +24,7 @@ import org.apache.xalan.xpath3.FnIndexOfTests;
import org.apache.xalan.xpath3.FnStringJoinTests;
import org.apache.xalan.xpath3.FnTokenizeTests;
import org.apache.xalan.xpath3.FnUnparsedTextTests;
+import org.apache.xalan.xpath3.IfExprTests;
import org.apache.xalan.xpath3.InlineFunctionItemExprTests;
import org.apache.xalan.xpath3.RangeExprTests;
import org.apache.xalan.xpath3.SequenceTests;
@@ -54,7 +55,7 @@ import org.junit.runners.Suite.SuiteClasses;
FnIndexOfTests.class, SequenceTests.class, RangeExprTests.class,
W3c_xslt30_IterateTests.class, W3c_xslt30_AxesTests.class, XslIterateTests.class,
ValueComparisonTests.class, InlineFunctionItemExprTests.class, FnForEachTests.class,
- FnFilterTests.class, DynamicFunctionCallTests.class })
+ FnFilterTests.class, DynamicFunctionCallTests.class, IfExprTests.class })
public class AllXsl3Tests {
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org