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 04:46:43 UTC
(xalan-java) branch xalan-j_xslt3.0_mvn updated: improving implementation of xsl:apply-templates instruction to support xsl 3 use cases, 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 cce212d98 improving implementation of xsl:apply-templates instruction to support xsl 3 use cases, along with related working test case
cce212d98 is described below
commit cce212d986d219a0ed1cc9bb36bf09f5ea37bafd
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sat Mar 22 10:16:28 2025 +0530
improving implementation of xsl:apply-templates instruction to support xsl 3 use cases, along with related working test case
---
README | 4 +-
.../apache/xalan/templates/ElemApplyTemplates.java | 148 +++++++++++++++------
.../org/apache/xalan/templates/TemplateList.java | 32 ++++-
.../templates/TemplateSubPatternAssociation.java | 17 ++-
.../xslt/util/XslTransformSharedDatastore.java | 6 +
.../org/apache/xpath/compiler/XPathParser.java | 25 +++-
.../org/apache/xpath/functions/FuncReplace.java | 12 +-
.../org/apache/xpath/functions/FuncStartsWith.java | 28 +++-
.../apache/xalan/tests/xslt3/XslTemplateTests.java | 10 ++
src/test/resources/xsl_template/gold/test17.out | 16 +++
src/test/resources/xsl_template/input.txt | 7 +
src/test/resources/xsl_template/test17.xsl | 60 +++++++++
12 files changed, 303 insertions(+), 62 deletions(-)
diff --git a/README b/README
index 835d73081..d9e08bffc 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: 948, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 15.548 s - in 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]
[INFO] Results:
[INFO]
-[INFO] Tests run: 948, Failures: 0, Errors: 0, Skipped: 0
+[INFO] Tests run: 949, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
diff --git a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
index 72d2d043d..de8859b07 100644
--- a/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
+++ b/src/main/java/org/apache/xalan/templates/ElemApplyTemplates.java
@@ -20,7 +20,11 @@
*/
package org.apache.xalan.templates;
+import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.Vector;
import javax.xml.transform.SourceLocator;
@@ -53,6 +57,7 @@ import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import xml.xpath31.processor.types.XSAnyAtomicType;
+import xml.xpath31.processor.types.XSBoolean;
/**
* Implementation of XSLT xsl:apply-templates element.
@@ -216,8 +221,7 @@ public class ElemApplyTemplates extends ElemCallTemplate
if (m_selectExpression instanceof XPathSequenceConstructor) {
resultSeq = (ResultSequence)(((XPathSequenceConstructor)m_selectExpression).execute(xctxt));
- if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
- // Added for XSLT 3.0
+ if (isAllSeqItemsXdmAtomicValues(resultSeq)) {
executeXslTransformAtomicValueSeq(transformer, xctxt, resultSeq);
return;
@@ -253,20 +257,8 @@ public class ElemApplyTemplates extends ElemCallTemplate
}
}
}
- else if (varEvalResult instanceof XSAnyAtomicType) {
- // Added for XSLT 3.0
- final StylesheetRoot sroot1 = transformer.getStylesheet();
- final TemplateList tlOne = sroot1.getTemplateListComposed();
- ElemTemplate template = tlOne.getTemplate(".");
-
- xctxt.setXPath3ContextItem(varEvalResult);
-
- for (ElemTemplateElement t = template.m_firstChild; t != null; t = t.m_nextSibling) {
- xctxt.setSAXLocator(t);
- transformer.pushElemTemplateElement(t);
- t.execute(transformer);
- transformer.popElemTemplateElement();
- }
+ else if (varEvalResult instanceof XSAnyAtomicType) {
+ executeXslTransformAtomicValue(transformer, xctxt, varEvalResult);
return;
}
@@ -302,20 +294,8 @@ public class ElemApplyTemplates extends ElemCallTemplate
else if (varEvalResult instanceof XNodeSet) {
sourceNodes = ((XNodeSet)varEvalResult).asIterator(xctxt, sourceNode);
}
- else if (isXdmItemAtomicValue(varEvalResult)) {
- // Added for XSLT 3.0
- final StylesheetRoot sroot1 = transformer.getStylesheet();
- final TemplateList tlOne = sroot1.getTemplateListComposed();
- ElemTemplate template = tlOne.getTemplate(".");
-
- xctxt.setXPath3ContextItem(varEvalResult);
-
- for (ElemTemplateElement t = template.m_firstChild; t != null; t = t.m_nextSibling) {
- xctxt.setSAXLocator(t);
- transformer.pushElemTemplateElement(t);
- t.execute(transformer);
- transformer.popElemTemplateElement();
- }
+ else if (isXdmItemAtomicValue(varEvalResult)) {
+ executeXslTransformAtomicValue(transformer, xctxt, varEvalResult);
return;
}
@@ -657,27 +637,115 @@ public class ElemApplyTemplates extends ElemCallTemplate
}
/**
- * This method definition does, an XSL transformation of a
- * sequence of XDM atomic values.
+ * This method definition does, an XSL transformation for a sequence of
+ * XDM atomic values.
*/
private void executeXslTransformAtomicValueSeq(TransformerImpl transformer, final XPathContext xctxt,
ResultSequence resultSeq) throws TransformerException {
final StylesheetRoot sroot = transformer.getStylesheet();
final TemplateList tl = sroot.getTemplateListComposed();
- ElemTemplate template = tl.getTemplate(".");
-
+
+ Hashtable templateListHashTable = tl.getPatternTable();
+ Set hashTableEntrySet = templateListHashTable.entrySet();
+ Iterator iter = hashTableEntrySet.iterator();
+
for (int idx = 0; idx < resultSeq.size(); idx++) {
XObject xObj = resultSeq.item(idx);
+ executeXslTransformAtomicValue(transformer, xctxt, xObj, iter);
+
+ // Reset an iterator object instance
+ iter = hashTableEntrySet.iterator();
+ }
+ }
+
+ /**
+ * This method initializes few XSL transform context variables, and does
+ * transformation for one XDM atomic value.
+ */
+ private void executeXslTransformAtomicValue(TransformerImpl transformer, final XPathContext xctxt,
+ XObject xObj) throws TransformerException {
+
+ final StylesheetRoot sroot = transformer.getStylesheet();
+ final TemplateList tl = sroot.getTemplateListComposed();
+
+ Hashtable templateListHashTable = tl.getPatternTable();
+ Set hashTableEntrySet = templateListHashTable.entrySet();
+ Iterator iter = hashTableEntrySet.iterator();
+
+ executeXslTransformAtomicValue(transformer, xctxt, xObj, iter);
+
+ // Reset an iterator object instance
+ iter = hashTableEntrySet.iterator();
+ }
+
+ /**
+ * 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 {
+
+ ElemTemplate template = null;
+
+ SourceLocator srcLocator = xctxt.getSAXLocator();
+
+ XObject prevCtxItem = xctxt.getXPath3ContextItem();
+
+ while (iter.hasNext()) {
+ Entry<Object, Object> hashTableEntry = (Entry<Object, Object>)iter.next();
+ Object hTableKeyObj = hashTableEntry.getKey();
+ TemplateSubPatternAssociation htValueObj = (TemplateSubPatternAssociation)(hashTableEntry.getValue());
+ template = htValueObj.getTemplate();
+
xctxt.setXPath3ContextItem(xObj);
- for (ElemTemplateElement t = template.m_firstChild;
- t != null; t = t.m_nextSibling) {
- xctxt.setSAXLocator(t);
- transformer.pushElemTemplateElement(t);
- t.execute(transformer);
- transformer.popElemTemplateElement();
+
+ 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();
+ }
+
+ if (isSuccess) {
+ for (ElemTemplateElement t = template.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 121564a42..186b7003a 100644
--- a/src/main/java/org/apache/xalan/templates/TemplateList.java
+++ b/src/main/java/org/apache/xalan/templates/TemplateList.java
@@ -27,6 +27,7 @@ import java.util.Vector;
import javax.xml.transform.TransformerException;
import org.apache.xalan.res.XSLTErrorResources;
+import org.apache.xalan.xslt.util.XslTransformSharedDatastore;
import org.apache.xml.dtm.DTM;
import org.apache.xml.utils.QName;
import org.apache.xpath.Expression;
@@ -109,9 +110,10 @@ public class TemplateList implements java.io.Serializable
XPath templateMatchXPath = template.getMatch();
String xpathPatternStr = templateMatchXPath.getPatternString();
- if (".".equalsIgnoreCase(xpathPatternStr)) {
- // added for XSLT 3.0
- m_patternTable.put(String.valueOf(xpathPatternStr), template);
+ if (".".equals(xpathPatternStr) || xpathPatternStr.startsWith(".[")) {
+ insertPatternInTable(String.valueOf(xpathPatternStr), template);
+
+ XslTransformSharedDatastore.templateMatchDotPatternPredicateStr = null;
}
else if (matchExpr instanceof StepPattern)
{
@@ -135,7 +137,7 @@ public class TemplateList implements java.io.Serializable
}
}
- /** Flag to indicate whether in DEBUG mode */
+/** Flag to indicate whether in DEBUG mode */
final static boolean DEBUG = false;
/**
@@ -196,7 +198,7 @@ public class TemplateList implements java.io.Serializable
Enumeration associations = m_patternTable.elements();
while (associations.hasMoreElements())
- {
+ {
TemplateSubPatternAssociation head =
(TemplateSubPatternAssociation) associations.nextElement();
TemplateSubPatternAssociation wild = m_wildCardPatterns;
@@ -382,6 +384,22 @@ public class TemplateList implements java.io.Serializable
}
}
}
+
+ /**
+ * Add a template to the template list.
+ *
+ * This method definition supports, XSLT 3.0 xsl:template match pattern
+ * strings ".", .[...].
+ *
+ * @param pattern
+ * @param template
+ */
+ private void insertPatternInTable(String xpathMatchPatternStr, ElemTemplate template) {
+ TemplateSubPatternAssociation association =
+ new TemplateSubPatternAssociation(template, null, xpathMatchPatternStr);
+
+ m_patternTable.put(xpathMatchPatternStr, association);
+ }
/**
* Given a match pattern and template association, return the
@@ -937,4 +955,8 @@ public class TemplateList implements java.io.Serializable
}
}
+ public Hashtable getPatternTable() {
+ return m_patternTable;
+ }
+
}
diff --git a/src/main/java/org/apache/xalan/templates/TemplateSubPatternAssociation.java b/src/main/java/org/apache/xalan/templates/TemplateSubPatternAssociation.java
index 0ff01ebe2..d23ac78d7 100644
--- a/src/main/java/org/apache/xalan/templates/TemplateSubPatternAssociation.java
+++ b/src/main/java/org/apache/xalan/templates/TemplateSubPatternAssociation.java
@@ -63,12 +63,17 @@ class TemplateSubPatternAssociation implements Serializable, Cloneable
*/
TemplateSubPatternAssociation(ElemTemplate template, StepPattern pattern, String pat)
{
-
- m_pattern = pat;
- m_template = template;
- m_stepPattern = pattern;
- m_targetString = m_stepPattern.getTargetString();
- m_wild = m_targetString.equals("*");
+ m_pattern = pat;
+ m_template = template;
+ m_stepPattern = pattern;
+ if (m_stepPattern != null) {
+ m_targetString = m_stepPattern.getTargetString();
+ m_wild = m_targetString.equals("*");
+ }
+ else {
+ m_targetString = m_pattern;
+ m_wild = m_targetString.equals("*");
+ }
}
/**
diff --git a/src/main/java/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java b/src/main/java/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
index a01d65e8a..e24689521 100644
--- a/src/main/java/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
+++ b/src/main/java/org/apache/xalan/xslt/util/XslTransformSharedDatastore.java
@@ -71,5 +71,11 @@ public class XslTransformSharedDatastore {
* intersect or except.
*/
public static StringBuffer xpathNodeCombiningExprRhsStrBuff;
+
+ /**
+ * This class field represents, XPath predicate suffix of XSL
+ * template definition like xsl:template match=".[..]".
+ */
+ public static String templateMatchDotPatternPredicateStr;
}
diff --git a/src/main/java/org/apache/xpath/compiler/XPathParser.java b/src/main/java/org/apache/xpath/compiler/XPathParser.java
index 8e9737f6b..f7d90e4fd 100644
--- a/src/main/java/org/apache/xpath/compiler/XPathParser.java
+++ b/src/main/java/org/apache/xpath/compiler/XPathParser.java
@@ -157,8 +157,8 @@ public class XPathParser
* we translate that within this XPath parser implementation, to an XPath
* range "to" expression using this class field (this equivalently produces
* an xdm empty sequence). There may be other direct ways of implementing this.
- * Pls review.
*/
+ // REVISIT
public static final String XPATH_EXPR_STR_EMPTY_SEQUENCE = "1 to 0";
private static final List<String> XPATH_OP_ARR_TOKENS_LIST = Arrays.asList(XPATH_OP_ARR);
@@ -1642,12 +1642,15 @@ public class XPathParser
* For named function references specified with syntax functionNameString#integerLiteral,
* check whether integerLiteral (i.e, function arity, of the function to be called) is
* an integer >= 0.
+ *
+ * Function arity is defined as, "The number of arguments the function accepts".
*/
private boolean isFuncArityWellFormedForNamedFuncRef(String funcRefStr) {
+
boolean isFuncArityWellFormed = true;
int idx = funcRefStr.indexOf('#');
- String intStr = funcRefStr.substring(idx+1);
+ String intStr = funcRefStr.substring(idx + 1);
Integer intVal = null;
try {
intVal = Integer.valueOf(intStr);
@@ -4587,12 +4590,28 @@ public class XPathParser
// strings, that represent XDM atomic values.
Object nodeTestOp = Keywords.getNodeType(m_token);
- int nt = ((Integer) nodeTestOp).intValue();
+ int nt = ((Integer)nodeTestOp).intValue();
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), nt);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
consumeExpected('.');
+
+ if (tokenIs('[')) {
+ StringBuffer strBuff = new StringBuffer();
+ consumeExpected('[');
+ while (m_token != null) {
+ if (tokenIs(']')) {
+ consumeExpected(']');
+ }
+ else {
+ strBuff.append(m_token);
+ nextToken();
+ }
+ }
+
+ XslTransformSharedDatastore.templateMatchDotPatternPredicateStr = strBuff.toString();
+ }
}
else
{
diff --git a/src/main/java/org/apache/xpath/functions/FuncReplace.java b/src/main/java/org/apache/xpath/functions/FuncReplace.java
index 8552dfe1e..836a4a17d 100644
--- a/src/main/java/org/apache/xpath/functions/FuncReplace.java
+++ b/src/main/java/org/apache/xpath/functions/FuncReplace.java
@@ -25,6 +25,7 @@ import javax.xml.transform.SourceLocator;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
import org.apache.xpath.XPathContext;
+import org.apache.xpath.axes.SelfIteratorNoPredicate;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.regex.Matcher;
import org.apache.xpath.regex.PatternSyntaxException;
@@ -58,8 +59,15 @@ public class FuncReplace extends Function4Args {
XObject result = null;
SourceLocator srcLocator = xctxt.getSAXLocator();
-
- String inputStr = XslTransformEvaluationHelper.getStrVal(m_arg0.execute(xctxt));
+
+ XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+ String inputStr = null;
+ if ((m_arg0 instanceof SelfIteratorNoPredicate) && (xpath3ContextItem != null)) {
+ inputStr = XslTransformEvaluationHelper.getStrVal(xpath3ContextItem);
+ }
+ else {
+ inputStr = XslTransformEvaluationHelper.getStrVal(m_arg0.execute(xctxt));
+ }
String patternStr = XslTransformEvaluationHelper.getStrVal(m_arg1.execute(xctxt));
String replacementStr = XslTransformEvaluationHelper.getStrVal(m_arg2.execute(xctxt));
diff --git a/src/main/java/org/apache/xpath/functions/FuncStartsWith.java b/src/main/java/org/apache/xpath/functions/FuncStartsWith.java
index e99773318..8f57394c2 100644
--- a/src/main/java/org/apache/xpath/functions/FuncStartsWith.java
+++ b/src/main/java/org/apache/xpath/functions/FuncStartsWith.java
@@ -20,12 +20,15 @@
*/
package org.apache.xpath.functions;
+import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
import org.apache.xpath.XPathContext;
+import org.apache.xpath.axes.SelfIteratorNoPredicate;
import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XObject;
/**
- * Execute the StartsWith() function.
+ * Implementation of XPath fn:starts-with function.
+ *
* @xsl.usage advanced
*/
public class FuncStartsWith extends Function2Args
@@ -33,8 +36,9 @@ public class FuncStartsWith extends Function2Args
static final long serialVersionUID = 2194585774699567928L;
/**
- * Execute the function. The function must return
+ * Execute the function. The function must return
* a valid object.
+ *
* @param xctxt The current execution context.
* @return A valid XObject.
*
@@ -42,7 +46,23 @@ public class FuncStartsWith extends Function2Args
*/
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
{
- return m_arg0.execute(xctxt).xstr().startsWith(m_arg1.execute(xctxt).xstr())
- ? XBoolean.S_TRUE : XBoolean.S_FALSE;
+ XObject result = null;
+
+ XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+
+ XObject arg1XObj = m_arg1.execute(xctxt);
+ String arg1StrValue = XslTransformEvaluationHelper.getStrVal(arg1XObj);
+
+ if ((m_arg0 instanceof SelfIteratorNoPredicate) && (xpath3ContextItem != null)) {
+ String arg0StrValue = XslTransformEvaluationHelper.getStrVal(xpath3ContextItem);
+ result = arg0StrValue.startsWith(arg1StrValue) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
+ }
+ else {
+ XObject xpathEvalResult = m_arg0.execute(xctxt);
+ String arg0StrValue = XslTransformEvaluationHelper.getStrVal(xpathEvalResult);
+ result = arg0StrValue.startsWith(arg1StrValue) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
+ }
+
+ return result;
}
}
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 963a1bb5d..5714f52ec 100644
--- a/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
+++ b/src/test/java/org/apache/xalan/tests/xslt3/XslTemplateTests.java
@@ -207,5 +207,15 @@ public class XslTemplateTests extends XSLTransformTestsUtil {
runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
}
+
+ @Test
+ public void xslTemplateTest17() {
+ String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test17.xsl";
+ String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test17.xsl";
+
+ String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test17.out";
+
+ runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+ }
}
diff --git a/src/test/resources/xsl_template/gold/test17.out b/src/test/resources/xsl_template/gold/test17.out
new file mode 100644
index 000000000..650f441e5
--- /dev/null
+++ b/src/test/resources/xsl_template/gold/test17.out
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>XSL transformation result</title>
+</head>
+<body>
+<br>
+<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>
+<h1> Your's sincerely</h1>
+<h3>--</h3>
+<h3>Apache Xalan</h3>
+</body>
+</html>
diff --git a/src/test/resources/xsl_template/input.txt b/src/test/resources/xsl_template/input.txt
new file mode 100644
index 000000000..538546414
--- /dev/null
+++ b/src/test/resources/xsl_template/input.txt
@@ -0,0 +1,7 @@
+Hello world, this text file is used for testing purpose
+== Thanks for reading this
+Many thanks
+:: Thank you
+== Your's sincerely
+--
+Apache Xalan
diff --git a/src/test/resources/xsl_template/test17.xsl b/src/test/resources/xsl_template/test17.xsl
new file mode 100644
index 000000000..2a7f15a2c
--- /dev/null
+++ b/src/test/resources/xsl_template/test17.xsl
@@ -0,0 +1,60 @@
+<?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 XSL stylesheet example's algorithm has been borrowed
+ from XSLT 3.0 spec.
+ -->
+
+ <xsl:output method="html"/>
+
+ <xsl:template match="/">
+ <html>
+ <head>
+ <title>XSL transformation result</title>
+ </head>
+ <body>
+ <br/><xsl:apply-templates select="unparsed-text-lines('input.txt')"/>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template match=".[starts-with(., '==')]">
+ <h1><xsl:value-of select="replace(., '==', '')"/></h1>
+ </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