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 2025/03/22 09:02:52 UTC
(xalan-java) branch xalan-j_xslt3.0_mvn updated: improving implementation of xsl 3 xsl:template processing, when xsl:template element has 'mode' attribute and xsl:template match pattern string starts with '.', along with related working test case
This is an automated email from the ASF dual-hosted git repository.
mukulg pushed a commit to branch xalan-j_xslt3.0_mvn
in repository https://gitbox.apache.org/repos/asf/xalan-java.git
The following commit(s) were added to refs/heads/xalan-j_xslt3.0_mvn by this push:
new 7902b504f improving implementation of xsl 3 xsl:template processing, when xsl:template element has 'mode' attribute and xsl:template match pattern string starts with '.', along with related working test case
7902b504f is described below
commit 7902b504fe3b6ed1e3f1499ef00b49bb3b379809
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sat Mar 22 14:32:42 2025 +0530
improving implementation of xsl 3 xsl:template processing, when xsl:template element has 'mode' attribute and xsl:template match pattern string starts with '.', along with related working test case
---
README | 4 +-
.../java/org/apache/xalan/templates/Constants.java | 2 +
.../apache/xalan/templates/ElemApplyTemplates.java | 136 ++++++++++++---------
.../org/apache/xalan/templates/TemplateList.java | 15 +++
.../apache/xalan/tests/xslt3/XslTemplateTests.java | 10 ++
src/test/resources/xsl_template/gold/test18.out | 15 +++
src/test/resources/xsl_template/test18.xsl | 77 ++++++++++++
7 files changed, 201 insertions(+), 58 deletions(-)
diff --git a/README b/README
index d9e08bffc..3d91757aa 100644
--- a/README
+++ b/README
@@ -59,11 +59,11 @@ This produces Maven build output with trailing information like following:
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.apache.xalan.tests.main.AllXsl3Tests
-[INFO] Tests run: 949, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 44.034 s - in org.apache.xalan.tests.main.AllXsl3Tests
+[INFO] Tests run: 950, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 19.383 s - in org.apache.xalan.tests.main.AllXsl3Tests
[INFO]
[INFO] Results:
[INFO]
-[INFO] Tests run: 949, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 950, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
diff --git a/src/main/java/org/apache/xalan/templates/Constants.java b/src/main/java/org/apache/xalan/templates/Constants.java
index 9874ba180..ddcdc0e02 100644
--- a/src/main/java/org/apache/xalan/templates/Constants.java
+++ b/src/main/java/org/apache/xalan/templates/Constants.java
@@ -442,7 +442,9 @@ public class Constants extends org.apache.xml.utils.Constants
ATTRVAL_NAN = "NaN",
DEFAULT_DECIMAL_FORMAT = "#default";
+ public static final String XSL3_PATTERN_TABLE_DELIM = "#####";
/** temp dummy */
public static final String ATTRNAME_XXXX = "XXXX";
+
}
diff --git a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
index de8859b07..f475aaf7f 100644
--- a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
+++ b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
@@ -212,17 +212,16 @@ public class ElemApplyTemplates extends ElemCallTemplate
DTMIterator sourceNodes = null;
- SourceLocator srcLocator = xctxt.getSAXLocator();
-
- XObject varEvalResult = null;
-
+ SourceLocator srcLocator = xctxt.getSAXLocator();
+ XObject varEvalResult = null;
ResultSequence resultSeq = null;
+ QName xslTemplateInvokeMode = getMode();
if (m_selectExpression instanceof XPathSequenceConstructor) {
resultSeq = (ResultSequence)(((XPathSequenceConstructor)m_selectExpression).execute(xctxt));
if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
- executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
+ executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq, xslTemplateInvokeMode);
return;
}
@@ -243,7 +242,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
resultSeq = (ResultSequence)varEvalResult;
if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
- executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
+ executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq, xslTemplateInvokeMode);
return;
}
@@ -258,7 +257,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
}
}
else if (varEvalResult instanceof XSAnyAtomicType) {
- executeXslTransformAtomicValue(transformer, xctxt, varEvalResult);
+ executeXslTransformAtomicValue(transformer, xctxt, varEvalResult, xslTemplateInvokeMode);
return;
}
@@ -277,7 +276,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
resultSeq = (ResultSequence)varEvalResult;
if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
- executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
+ executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq, xslTemplateInvokeMode);
return;
}
@@ -295,7 +294,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
sourceNodes = ((XNodeSet)varEvalResult).asIterator(xctxt, sourceNode);
}
else if (isXdmItemAtomicValue(varEvalResult)) {
- executeXslTransformAtomicValue(transformer, xctxt, varEvalResult);
+ executeXslTransformAtomicValue(transformer, xctxt, varEvalResult, xslTemplateInvokeMode);
return;
}
@@ -641,7 +640,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
* XDM atomic values.
*/
private void executeXslTransformAtomicValueSeq(TransformerImpl transformer, final XPathContext xctxt,
- ResultSequence resultSeq) throws TransformerException {
+ ResultSequence resultSeq, QName xslTemplateInvokeMode) throws TransformerException {
final StylesheetRoot sroot = transformer.getStylesheet();
final TemplateList tl = sroot.getTemplateListComposed();
@@ -652,7 +651,8 @@ public class ElemApplyTemplates extends ElemCallTemplate
for (int idx = 0; idx < resultSeq.size(); idx++) {
XObject xObj = resultSeq.item(idx);
- executeXslTransformAtomicValue(transformer, xctxt, xObj, iter);
+
+ executeXslTransformAtomicValue(transformer, xctxt, xObj, iter, xslTemplateInvokeMode);
// Reset an iterator object instance
iter = hashTableEntrySet.iterator();
@@ -664,7 +664,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
* transformation for one XDM atomic value.
*/
private void executeXslTransformAtomicValue(TransformerImpl transformer, final XPathContext xctxt,
- XObject xObj) throws TransformerException {
+ XObject xObj, QName xslTemplateInvokeMode) throws TransformerException {
final StylesheetRoot sroot = transformer.getStylesheet();
final TemplateList tl = sroot.getTemplateListComposed();
@@ -673,9 +673,9 @@ public class ElemApplyTemplates extends ElemCallTemplate
Set hashTableEntrySet = templateListHashTable.entrySet();
Iterator iter = hashTableEntrySet.iterator();
- executeXslTransformAtomicValue(transformer, xctxt, xObj, iter);
+ executeXslTransformAtomicValue(transformer, xctxt, xObj, iter, xslTemplateInvokeMode);
- // Reset an iterator object instance
+ // Recreate an iterator object instance
iter = hashTableEntrySet.iterator();
}
@@ -683,9 +683,9 @@ public class ElemApplyTemplates extends ElemCallTemplate
* This method definition does, an XSL transform for one XDM atomic value.
*/
private void executeXslTransformAtomicValue(TransformerImpl transformer, final XPathContext xctxt, XObject xObj,
- Iterator iter) throws TransformerException {
+ Iterator iter, QName xslTemplateInvokeMode) throws TransformerException {
- ElemTemplate template = null;
+ ElemTemplate elemTemplate = null;
SourceLocator srcLocator = xctxt.getSAXLocator();
@@ -693,56 +693,80 @@ public class ElemApplyTemplates extends ElemCallTemplate
while (iter.hasNext()) {
Entry<Object, Object> hashTableEntry = (Entry<Object, Object>)iter.next();
- Object hTableKeyObj = hashTableEntry.getKey();
- TemplateSubPatternAssociation htValueObj = (TemplateSubPatternAssociation)(hashTableEntry.getValue());
- template = htValueObj.getTemplate();
+ Object hashTableKeyObj = hashTableEntry.getKey();
+ TemplateSubPatternAssociation hashTableValueObj = (TemplateSubPatternAssociation)(hashTableEntry.getValue());
+ elemTemplate = hashTableValueObj.getTemplate();
- xctxt.setXPath3ContextItem(xObj);
+ QName templateDefnMode = elemTemplate.getMode();
+ boolean templateSelected = false;
+ if ((xslTemplateInvokeMode != null) && (templateDefnMode != null)) {
+ if (xslTemplateInvokeMode.equals(templateDefnMode)) {
+ templateSelected = true;
+ }
+ }
+ else if ((xslTemplateInvokeMode != null) && (templateDefnMode == null)) {
+ templateSelected = false;
+ }
+ else if ((xslTemplateInvokeMode == null) && (templateDefnMode != null)) {
+ templateSelected = false;
+ }
+ else {
+ templateSelected = true;
+ }
- String keyValueStr = (String)hTableKeyObj;
- if (keyValueStr.startsWith(".[")) {
- String xpathStr = keyValueStr.substring(2);
- xpathStr = xpathStr.substring(0, xpathStr.length() - 1);
- XPath xpath = new XPath(xpathStr, srcLocator, xctxt.getNamespaceContext(),
- XPath.SELECT, null);
- XObject xpathEvalResult = xpath.execute(xctxt, DTM.NULL, xctxt.getNamespaceContext());
- boolean isSuccess = false;
- if (xpathEvalResult instanceof XBooleanStatic) {
- XBooleanStatic xBoolStatic = (XBooleanStatic)xpathEvalResult;
- isSuccess = xBoolStatic.bool();
- }
- else if (xpathEvalResult instanceof XBoolean) {
- XBoolean xBoolean = (XBoolean)xpathEvalResult;
- isSuccess = xBoolean.bool();
- }
- else if (xpathEvalResult instanceof XSBoolean) {
- XSBoolean xsBoolean = (XSBoolean)xpathEvalResult;
- isSuccess = xsBoolean.bool();
- }
+ String keyValueStr = (String)hashTableKeyObj;
+ int index1 = keyValueStr.indexOf(Constants.XSL3_PATTERN_TABLE_DELIM);
+ if (index1 >= 0) {
+ keyValueStr = keyValueStr.substring(0, index1);
+ }
+
+ if (templateSelected) {
+ xctxt.setXPath3ContextItem(xObj);
+
+ if (keyValueStr.startsWith(".[")) {
+ String xpathStr = keyValueStr.substring(2);
+ xpathStr = xpathStr.substring(0, xpathStr.length() - 1);
+ XPath xpath = new XPath(xpathStr, srcLocator, xctxt.getNamespaceContext(),
+ XPath.SELECT, null);
+ XObject xpathEvalResult = xpath.execute(xctxt, DTM.NULL, xctxt.getNamespaceContext());
+ boolean isSuccess = false;
+ if (xpathEvalResult instanceof XBooleanStatic) {
+ XBooleanStatic xBoolStatic = (XBooleanStatic)xpathEvalResult;
+ isSuccess = xBoolStatic.bool();
+ }
+ else if (xpathEvalResult instanceof XBoolean) {
+ XBoolean xBoolean = (XBoolean)xpathEvalResult;
+ isSuccess = xBoolean.bool();
+ }
+ else if (xpathEvalResult instanceof XSBoolean) {
+ XSBoolean xsBoolean = (XSBoolean)xpathEvalResult;
+ isSuccess = xsBoolean.bool();
+ }
- if (isSuccess) {
- for (ElemTemplateElement t = template.m_firstChild;
- t != null; t = t.m_nextSibling) {
+ if (isSuccess) {
+ for (ElemTemplateElement t = elemTemplate.m_firstChild;
+ t != null; t = t.m_nextSibling) {
+ xctxt.setSAXLocator(t);
+ transformer.pushElemTemplateElement(t);
+ t.execute(transformer);
+ transformer.popElemTemplateElement();
+ }
+
+ break;
+ }
+ }
+ else if (".".equals(keyValueStr)) {
+ for (ElemTemplateElement t = elemTemplate.m_firstChild;
+ t != null; t = t.m_nextSibling) {
xctxt.setSAXLocator(t);
transformer.pushElemTemplateElement(t);
t.execute(transformer);
transformer.popElemTemplateElement();
}
-
+
break;
- }
- }
- else if (".".equals(keyValueStr)) {
- for (ElemTemplateElement t = template.m_firstChild;
- t != null; t = t.m_nextSibling) {
- xctxt.setSAXLocator(t);
- transformer.pushElemTemplateElement(t);
- t.execute(transformer);
- transformer.popElemTemplateElement();
}
-
- break;
- }
+ }
}
xctxt.setXPath3ContextItem(prevCtxItem);
diff --git a/src/main/java/org/apache/xalan/templates/TemplateList.java b/src/main/java/org/apache/xalan/templates/TemplateList.java
index 186b7003a..141f9ee6c 100644
--- a/src/main/java/org/apache/xalan/templates/TemplateList.java
+++ b/src/main/java/org/apache/xalan/templates/TemplateList.java
@@ -398,6 +398,21 @@ public class TemplateList implements java.io.Serializable
TemplateSubPatternAssociation association =
new TemplateSubPatternAssociation(template, null, xpathMatchPatternStr);
+ QName templateModeQname = template.getMode();
+ String templateModeStr = null;
+ if (templateModeQname != null) {
+ templateModeStr = templateModeQname.toString();
+ }
+ if (templateModeStr != null) {
+ /**
+ * This allows us to store within an Hashtable m_patternTable object,
+ * more than one xsl:template definition object instances having
+ * same value of "match" attribute but with different template
+ * definition mode names.
+ */
+ xpathMatchPatternStr = (xpathMatchPatternStr + Constants.XSL3_PATTERN_TABLE_DELIM + templateModeStr);
+ }
+
m_patternTable.put(xpathMatchPatternStr, association);
}
diff --git a/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java b/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
index 5714f52ec..a30cdf0aa 100644
--- a/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
+++ b/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
@@ -217,5 +217,15 @@ public class XslTemplateTests extends XSLTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslTemplateTest18() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test18.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test18.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/src/test/resources/xsl_template/gold/test18.out b/src/test/resources/xsl_template/gold/test18.out
new file mode 100644
index 000000000..d06b27ebc
--- /dev/null
+++ b/src/test/resources/xsl_template/gold/test18.out
@@ -0,0 +1,15 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>XSL transformation result</title>
+</head>
+<body>
+<h3>Hello world, this text file is used for testing purpose</h3>
+<h1>?? Thanks for reading this</h1>
+<h3>Many thanks</h3>
+<h2> Thank you</h2>
+<h2>## Your's sincerely</h2>
+<h3>--</h3>
+<h3>Apache Xalan</h3>
+</body>
+</html>
diff --git a/src/test/resources/xsl_template/test18.xsl b/src/test/resources/xsl_template/test18.xsl
new file mode 100644
index 000000000..4a5f8f896
--- /dev/null
+++ b/src/test/resources/xsl_template/test18.xsl
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ exclude-result-prefixes="xs"
+ version="3.0">
+
+ <!-- Author: mukulg@apache.org -->
+
+ <!-- An XSL 3 stylesheet test case, to test xsl:template match
+ with pattern ".", and ".[...]" (i.e, XPath string "."
+ followed by an XPath predicate.
+
+ This stylesheet also tests, related xsl:apply-templates
+ instruction having XSL 'mode' attribute.
+ -->
+
+ <xsl:output method="html"/>
+
+ <xsl:template match="/">
+ <html>
+ <head>
+ <title>XSL transformation result</title>
+ </head>
+ <body>
+ <xsl:for-each select="unparsed-text-lines('input.txt')">
+ <xsl:variable name="item1" select="." as="xs:string"/>
+ <xsl:choose>
+ <xsl:when test="position() eq 2">
+ <xsl:apply-templates select="$item1" mode="m1"/>
+ </xsl:when>
+ <xsl:when test="position() eq 5">
+ <xsl:apply-templates select="$item1" mode="m2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$item1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template match=".[starts-with(., '==')]" mode="m1">
+ <h1><xsl:value-of select="replace(., '==', '??')"/></h1>
+ </xsl:template>
+
+ <xsl:template match=".[starts-with(., '==')]" mode="m2">
+ <h2><xsl:value-of select="replace(., '==', '##')"/></h2>
+ </xsl:template>
+
+ <xsl:template match=".[starts-with(., '::')]">
+ <h2><xsl:value-of select="replace(., '::', '')"/></h2>
+ </xsl:template>
+
+ <xsl:template match=".">
+ <h3><xsl:value-of select="."/></h3>
+ </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