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 2024/07/25 17:03:48 UTC
(xalan-java) branch xalan-j_xslt3.0 updated: implementing xpath3.1 array information lookup using function call syntax, and few conformance test cases as well
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 2e8189226 implementing xpath3.1 array information lookup using function call syntax, and few conformance test cases as well
2e8189226 is described below
commit 2e8189226fb666404922130afeddd13672a19355
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Thu Jul 25 22:33:33 2024 +0530
implementing xpath3.1 array information lookup using function call syntax, and few conformance test cases as well
---
.../xpath/functions/XPathDynamicFunctionCall.java | 149 +++++++++++++++------
tests/org/apache/xalan/xpath3/XPathArrayTests.java | 10 ++
tests/org/apache/xalan/xpath3/XPathMapTests.java | 10 ++
tests/xpath_array/gold/test26.out | 8 ++
tests/xpath_array/test26.xsl | 43 ++++++
tests/xpath_maps/gold/test24.out | 5 +
tests/xpath_maps/test24.xsl | 43 ++++++
7 files changed, 226 insertions(+), 42 deletions(-)
diff --git a/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java b/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java
index d61298468..dc4f7482a 100644
--- a/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java
+++ b/src/org/apache/xpath/functions/XPathDynamicFunctionCall.java
@@ -42,18 +42,16 @@ import org.apache.xpath.composite.SequenceTypeData;
import org.apache.xpath.composite.SequenceTypeSupport;
import org.apache.xpath.objects.InlineFunctionParameter;
import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XPathArray;
import org.apache.xpath.objects.XPathInlineFunction;
import org.apache.xpath.objects.XPathMap;
import org.apache.xpath.objects.XString;
import xml.xpath31.processor.types.XSString;
-/*
- * This class implements XPath 3.1 dynamic function calls and map
- * lookup expressions.
- *
- * Ref : https://www.w3.org/TR/xpath-31/#id-dynamic-function-invocation,
- * https://www.w3.org/TR/xpath-31/#id-map-lookup
+/**
+ * This class implements XPath 3.1 dynamic function calls, and
+ * map/array information lookup using function call syntax.
*
* @author Mukul Gandhi <mu...@apache.org>
*
@@ -70,8 +68,8 @@ public class XPathDynamicFunctionCall extends Expression {
// 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;
+ private Vector m_vars;
+ private int m_globals_size;
public String getFuncRefVarName() {
return m_funcRefVarName;
@@ -133,37 +131,13 @@ public class XPathDynamicFunctionCall extends Expression {
if (functionRef != null) {
ElemTemplateElement elemTemplateElement = (ElemTemplateElement)xctxt.getNamespaceContext();
- List<XMLNSDecl> prefixTable = null;
+
+ List<XMLNSDecl> prefixTable = null;
if (elemTemplateElement != null) {
prefixTable = (List<XMLNSDecl>)elemTemplateElement.getPrefixTable();
}
- if (functionRef instanceof XPathMap) {
- XPathMap xpathMap = (XPathMap)functionRef;
- if (m_argList.size() != 1) {
- throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for map value lookup, should have only "
- + "one argument which needs to be one of map key name.", xctxt.getSAXLocator());
- }
- else {
- String argXPathStr = m_argList.get(0);
- if (prefixTable != null) {
- argXPathStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(argXPathStr,
- prefixTable);
- }
-
- XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
- if (fVars != null) {
- argXPath.fixupVariables(fVars, fGlobalsSize);
- }
-
- XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
- if (argValue instanceof XString) {
- argValue = new XSString(((XString)argValue).str());
- }
-
- evalResult = xpathMap.get(argValue);
- }
- }
- else if (functionRef instanceof XPathInlineFunction) {
+
+ if (functionRef instanceof XPathInlineFunction) {
XPathInlineFunction inlineFunction = (XPathInlineFunction)functionRef;
String inlineFnXPathStr = inlineFunction.getFuncBodyXPathExprStr();
@@ -189,8 +163,8 @@ public class XPathDynamicFunctionCall extends Expression {
XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(),
XPath.SELECT, null);
- if (fVars != null) {
- argXPath.fixupVariables(fVars, fGlobalsSize);
+ if (m_vars != null) {
+ argXPath.fixupVariables(m_vars, m_globals_size);
}
XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
@@ -228,8 +202,8 @@ public class XPathDynamicFunctionCall extends Expression {
XPath inlineFnXPath = new XPath(inlineFnXPathStr, srcLocator, xctxt.getNamespaceContext(),
XPath.SELECT, null);
- if (fVars != null) {
- inlineFnXPath.fixupVariables(fVars, fGlobalsSize);
+ if (m_vars != null) {
+ inlineFnXPath.fixupVariables(m_vars, m_globals_size);
}
evalResult = inlineFnXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
@@ -256,6 +230,68 @@ public class XPathDynamicFunctionCall extends Expression {
inlineFunctionVarMap.remove(key);
}
}
+ else if (functionRef instanceof XPathMap) {
+ XPathMap xpathMap = (XPathMap)functionRef;
+ if (m_argList.size() != 1) {
+ throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for map information lookup, needs to have "
+ + "1 argument which should be one of map's key name.",
+ xctxt.getSAXLocator());
+ }
+ else {
+ String argXPathStr = m_argList.get(0);
+ if (".".equals(argXPathStr)) {
+ XObject contextItem = xctxt.getXPath3ContextItem();
+ evalResult = xpathMap.get(contextItem);
+ }
+ else {
+ if (prefixTable != null) {
+ argXPathStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(argXPathStr,
+ prefixTable);
+ }
+
+ XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
+ if (m_vars != null) {
+ argXPath.fixupVariables(m_vars, m_globals_size);
+ }
+
+ XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
+ if (argValue instanceof XString) {
+ argValue = new XSString(((XString)argValue).str());
+ }
+
+ evalResult = xpathMap.get(argValue);
+ }
+ }
+ }
+ else if (functionRef instanceof XPathArray) {
+ XPathArray xpathArr = (XPathArray)functionRef;
+ if (m_argList.size() != 1) {
+ throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for array information lookup, needs to have "
+ + "1 argument which should be position within an array.",
+ xctxt.getSAXLocator());
+ }
+ else {
+ String argXPathStr = m_argList.get(0);
+ if (".".equals(argXPathStr)) {
+ XObject contextItem = xctxt.getXPath3ContextItem();
+ evalResult = getArrayLookupResult(xctxt, xpathArr, contextItem);
+ }
+ else {
+ if (prefixTable != null) {
+ argXPathStr = XslTransformEvaluationHelper.replaceNsUrisWithPrefixesOnXPathStr(argXPathStr,
+ prefixTable);
+ }
+
+ XPath argXPath = new XPath(argXPathStr, srcLocator, xctxt.getNamespaceContext(), XPath.SELECT, null);
+ if (m_vars != null) {
+ argXPath.fixupVariables(m_vars, m_globals_size);
+ }
+
+ XObject argValue = argXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
+ evalResult = getArrayLookupResult(xctxt, xpathArr, argValue);
+ }
+ }
+ }
}
else {
throw new javax.xml.transform.TransformerException("XPST0008 : Variable '" + m_funcRefVarName + "' has "
@@ -268,13 +304,42 @@ public class XPathDynamicFunctionCall extends Expression {
@Override
public void fixupVariables(Vector vars, int globalsSize) {
- fVars = (Vector)(vars.clone());
- fGlobalsSize = globalsSize;
+ m_vars = (Vector)(vars.clone());
+ m_globals_size = globalsSize;
}
@Override
public boolean deepEquals(Expression expr) {
return false;
}
+
+ /**
+ * Given an xdm array object, get array item at a specified index position.
+ */
+ private XObject getArrayLookupResult(XPathContext xctxt, XPathArray xpathArr, XObject indexVal)
+ throws TransformerException {
+ XObject evalResult;
+
+ String argValStr = XslTransformEvaluationHelper.getStrVal(indexVal);
+
+ Integer intVal = null;
+ try {
+ intVal = Integer.valueOf(argValStr);
+ if (!(intVal > 0 && (intVal <= xpathArr.size()))) {
+ throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for array information lookup, "
+ + "needs to have 1 numeric argument >= 1 specifying position "
+ + "within an array.", xctxt.getSAXLocator());
+ }
+ }
+ catch (NumberFormatException ex) {
+ throw new javax.xml.transform.TransformerException("XPTY0004 : Function call syntax for array information lookup, "
+ + "needs to have 1 numeric argument >= 1 specifying position "
+ + "within an array.", xctxt.getSAXLocator());
+ }
+
+ evalResult = xpathArr.get(intVal-1);
+
+ return evalResult;
+ }
}
diff --git a/tests/org/apache/xalan/xpath3/XPathArrayTests.java b/tests/org/apache/xalan/xpath3/XPathArrayTests.java
index fe9b0f78b..12cfe7f8b 100644
--- a/tests/org/apache/xalan/xpath3/XPathArrayTests.java
+++ b/tests/org/apache/xalan/xpath3/XPathArrayTests.java
@@ -297,5 +297,15 @@ public class XPathArrayTests extends XSLTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslArrayTest26() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test26.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test26.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test26.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/tests/org/apache/xalan/xpath3/XPathMapTests.java b/tests/org/apache/xalan/xpath3/XPathMapTests.java
index 195a42b0d..40d7cc9d6 100644
--- a/tests/org/apache/xalan/xpath3/XPathMapTests.java
+++ b/tests/org/apache/xalan/xpath3/XPathMapTests.java
@@ -277,5 +277,15 @@ public class XPathMapTests extends XSLTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslMapTest24() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test24.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test24.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test24.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/tests/xpath_array/gold/test26.out b/tests/xpath_array/gold/test26.out
new file mode 100644
index 000000000..7af5b1460
--- /dev/null
+++ b/tests/xpath_array/gold/test26.out
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?><array>
+ <item>5</item>
+ <item>6</item>
+ <item>7</item>
+ <item>8</item>
+ <item>9</item>
+ <item>10</item>
+</array>
diff --git a/tests/xpath_array/test26.xsl b/tests/xpath_array/test26.xsl
new file mode 100644
index 000000000..836c628b3
--- /dev/null
+++ b/tests/xpath_array/test26.xsl
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:array="http://www.w3.org/2005/xpath-functions/array"
+ exclude-result-prefixes="array"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSLT test case to test, XPath 3.1 array information lookup
+ using function call syntax. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/">
+ <xsl:variable name="arr1" select="[5,6,7,8,9,10]" as="array(*)"/>
+ <array>
+ <xsl:for-each select="1 to array:size($arr1)">
+ <item>
+ <xsl:value-of select="$arr1(.)"/>
+ </item>
+ </xsl:for-each>
+ </array>
+ </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>
diff --git a/tests/xpath_maps/gold/test24.out b/tests/xpath_maps/gold/test24.out
new file mode 100644
index 000000000..4c814503a
--- /dev/null
+++ b/tests/xpath_maps/gold/test24.out
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><map>
+ <item key="a">2</item>
+ <item key="b">3</item>
+ <item key="c">4</item>
+</map>
diff --git a/tests/xpath_maps/test24.xsl b/tests/xpath_maps/test24.xsl
new file mode 100644
index 000000000..3c0751e98
--- /dev/null
+++ b/tests/xpath_maps/test24.xsl
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:map="http://www.w3.org/2005/xpath-functions/map"
+ exclude-result-prefixes="map"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSLT test case to test, XPath 3.1 map information lookup
+ using function call syntax. -->
+
+ <xsl:output method="xml" indent="yes"/>
+
+ <xsl:template match="/">
+ <xsl:variable name="map1" select="map {'a' : 2, 'b' : 3, 'c' : 4}" as="map(*)"/>
+ <map>
+ <xsl:for-each select="sort(map:keys($map1))">
+ <item key="{.}">
+ <xsl:value-of select="$map1(.)"/>
+ </item>
+ </xsl:for-each>
+ </map>
+ </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>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org