[prev in list] [next in list] [prev in thread] [next in thread] 

List:       xalan-cvs
Subject:    [xalan-java] branch xalan-j_xslt3.0 updated: committing improvements to implementation of xpath 3.1 
From:       mukulg () apache ! org
Date:       2023-05-22 16:54:03
Message-ID: 168477444364.3505061.11156971050451718114 () gitbox2-he-fi ! apache ! org
[Download RAW message or body]

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 def4472b committing improvements to implementation of xpath 3.1 fn:tokenize \
function, and related codebase changes. also implementing xpath 3.1 function \
fn:unparsed-text.. def4472b is described below

commit def4472b3d5215e81f974ddd80c3c8ef49b00401
Author: Mukul Gandhi <gandhi.mukul@gmail.com>
AuthorDate: Mon May 22 22:23:27 2023 +0530

    committing improvements to implementation of xpath 3.1 fn:tokenize function, and \
                related codebase changes. also implementing xpath 3.1 function \
                fn:unparsed-text..
---
 src/org/apache/xalan/templates/ElemForEach.java    |  57 ++++++--
 src/org/apache/xalan/templates/ElemValueOf.java    |   3 +-
 src/org/apache/xalan/templates/ElemVariable.java   |  18 +++
 src/org/apache/xalan/templates/ElemWithParam.java  |  22 ++-
 src/org/apache/xpath/compiler/FunctionTable.java   |   9 +-
 src/org/apache/xpath/compiler/Keywords.java        |   3 +
 src/org/apache/xpath/functions/FuncConcat.java     |  56 ++++++--
 .../apache/xpath/functions/FuncUnparsedText.java   | 151 +++++++++++++++++++++
 src/org/apache/xpath/res/XPATHErrorResources.java  |   5 +
 9 files changed, 292 insertions(+), 32 deletions(-)

diff --git a/src/org/apache/xalan/templates/ElemForEach.java \
b/src/org/apache/xalan/templates/ElemForEach.java index eae82f1f..8a413977 100644
--- a/src/org/apache/xalan/templates/ElemForEach.java
+++ b/src/org/apache/xalan/templates/ElemForEach.java
@@ -38,6 +38,7 @@ import org.apache.xpath.XPathContext;
 import org.apache.xpath.functions.Function;
 import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XObject;
+import org.apache.xpath.operations.Variable;
 
 import java.io.ObjectInputStream;
 import java.io.IOException;
@@ -338,26 +339,29 @@ public class ElemForEach extends ElemTemplateElement implements \
ExpressionOwner  XPathContext xctxt = transformer.getXPathContext();
     
     if (m_selectExpression instanceof Function) {
+        // evaluate an xslt/xpath function reference.
+        // for example,
+        // <xsl:for-each select="tokenize(..)"> ...
         XObject evalResult = ((Function)m_selectExpression).execute(xctxt);
         if (evalResult instanceof ResultSequence) {
-            ResultSequence resultSeq = (ResultSequence)evalResult;
-            List<XObject> resultSeqItems = resultSeq.getResultSequenceItems();
-            for (int idx = 0; idx < resultSeqItems.size(); idx++) {
-                XObject resultSeqItem = resultSeqItems.get(idx);
-                xctxt.setXPath3ContextItem(resultSeqItem);
-                
-                for (ElemTemplateElement elemTemplateElem = this.m_firstChild; \
                elemTemplateElem != null; 
-                                                               elemTemplateElem = \
                elemTemplateElem.m_nextSibling) {
-                   xctxt.setSAXLocator(elemTemplateElem);
-                   transformer.setCurrentElement(elemTemplateElem);
-                   elemTemplateElem.execute(transformer);
-                }
-            }
-            
+            processResultSequence(transformer, xctxt, evalResult);
             return;
         }                
     }
     
+    if (m_selectExpression instanceof Variable) {
+        // evaluate an xslt variable reference.
+        // for example,
+        // <xsl:variable name="tokens" select="tokenize(..)"/>
+        // <xsl:for-each select="$tokens"> ...
+        XObject evalResult = ((Variable)m_selectExpression).execute(xctxt);
+        if (evalResult instanceof ResultSequence) {
+            processResultSequence(transformer, xctxt, evalResult);
+            return;
+        }
+    }
+    
+    // process the node-set, with body of xsl:for-each element as usual 
     final int sourceNode = xctxt.getCurrentNode();
     DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
 
@@ -577,4 +581,29 @@ public class ElemForEach extends ElemTemplateElement implements \
ExpressionOwner  os.defaultReadObject();
            m_xpath = null;
    }
+   
+   /*
+    * Process each of the XDM items in order, stored within a 'ResultSequence' 
+    * object, with the body of xsl:for-each element.
+    */
+   private void processResultSequence(TransformerImpl transformer,
+                                      XPathContext xctxt, XObject evalResult) 
+                                                              throws \
TransformerException { +       
+       ResultSequence resultSeq = (ResultSequence)evalResult;
+       List<XObject> resultSeqItems = resultSeq.getResultSequenceItems();
+       
+       for (int idx = 0; idx < resultSeqItems.size(); idx++) {
+           XObject resultSeqItem = resultSeqItems.get(idx);
+           xctxt.setXPath3ContextItem(resultSeqItem);
+           
+           for (ElemTemplateElement elemTemplateElem = this.m_firstChild; \
elemTemplateElem != null;  +                                                          \
elemTemplateElem = elemTemplateElem.m_nextSibling) { +              \
xctxt.setSAXLocator(elemTemplateElem); +              \
transformer.setCurrentElement(elemTemplateElem); +              \
elemTemplateElem.execute(transformer); +           }
+       }
+   }
+   
 }
diff --git a/src/org/apache/xalan/templates/ElemValueOf.java \
b/src/org/apache/xalan/templates/ElemValueOf.java index d32e6a80..96375ddc 100644
--- a/src/org/apache/xalan/templates/ElemValueOf.java
+++ b/src/org/apache/xalan/templates/ElemValueOf.java
@@ -265,14 +265,13 @@ public class ElemValueOf extends ElemTemplateElement
             XObject obj = expr.execute(xctxt);
 
             transformer.getTraceManager().fireSelectedEvent(current, this,
-                    "select", m_selectExpression, obj);
+                                                       "select", m_selectExpression, \
obj);  obj.dispatchCharactersEvents(rth);
           }
           else
           {
               XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
               if (m_isDot && xpath3ContextItem != null) {
-                  // this is currently, limited to work with xsl:for-each \
instruction  xpath3ContextItem.dispatchCharactersEvents(rth);   
               }
               else {
diff --git a/src/org/apache/xalan/templates/ElemVariable.java \
b/src/org/apache/xalan/templates/ElemVariable.java index d6d19b9a..21be5846 100644
--- a/src/org/apache/xalan/templates/ElemVariable.java
+++ b/src/org/apache/xalan/templates/ElemVariable.java
@@ -25,8 +25,11 @@ import javax.xml.transform.TransformerException;
 import org.apache.xalan.res.XSLTErrorResources;
 import org.apache.xalan.transformer.TransformerImpl;
 import org.apache.xml.utils.QName;
+import org.apache.xpath.Expression;
 import org.apache.xpath.XPath;
 import org.apache.xpath.XPathContext;
+import org.apache.xpath.functions.Function;
+import org.apache.xpath.objects.ResultSequence;
 import org.apache.xpath.objects.XNodeSetForDOM;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XRTreeFrag;
@@ -271,6 +274,9 @@ public class ElemVariable extends ElemTemplateElement
   {
 
     XObject var;
+    
+    final XPathContext xctxtOriginal = transformer.getXPathContext();
+    
     XPathContext xctxt = transformer.getXPathContext();
 
     xctxt.pushCurrentNode(sourceNode);
@@ -279,6 +285,15 @@ public class ElemVariable extends ElemTemplateElement
     {
       if (null != m_selectPattern)
       {
+        Expression selectExpression = m_selectPattern.getExpression();
+        if (selectExpression instanceof Function) {
+            XObject evalResult = ((Function)selectExpression).execute(xctxt);
+            if (evalResult instanceof ResultSequence) {
+                var = evalResult;
+                return var;
+            }
+        } 
+          
         var = m_selectPattern.execute(xctxt, sourceNode, this);
 
         var.allowDetachToRelease(false);
@@ -327,6 +342,9 @@ public class ElemVariable extends ElemTemplateElement
     {      
       xctxt.popCurrentNode();
     }
+    
+    // restoring the original xpath context, on the xslt transformer object.
+    transformer.setXPathContext(xctxtOriginal);
 
     return var;
   }
diff --git a/src/org/apache/xalan/templates/ElemWithParam.java \
b/src/org/apache/xalan/templates/ElemWithParam.java index 71fe8e15..67d72803 100644
--- a/src/org/apache/xalan/templates/ElemWithParam.java
+++ b/src/org/apache/xalan/templates/ElemWithParam.java
@@ -61,6 +61,11 @@ public class ElemWithParam extends ElemTemplateElement
    * @serial
    */
   private XPath m_selectPattern = null;
+  
+  /**
+   * True if the pattern is a simple ".".
+   */
+  private boolean m_isDot = false;
 
   /**
    * Set the "select" attribute.
@@ -71,7 +76,13 @@ public class ElemWithParam extends ElemTemplateElement
    */
   public void setSelect(XPath v)
   {
-    m_selectPattern = v;
+      m_selectPattern = v;
+    
+      if (v != null) {
+          String s = v.getPatternString();
+
+          m_isDot = (null != s) && s.equals(".");
+      }
   }
 
   /**
@@ -202,7 +213,14 @@ public class ElemWithParam extends ElemTemplateElement
     {
       if (null != m_selectPattern)
       {
-        var = m_selectPattern.execute(xctxt, sourceNode, this);
+        XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+        
+        if (m_isDot && xpath3ContextItem != null) {
+           var = xpath3ContextItem;   
+        }
+        else {
+           var = m_selectPattern.execute(xctxt, sourceNode, this);
+        }
 
         var.allowDetachToRelease(false);
 
diff --git a/src/org/apache/xpath/compiler/FunctionTable.java \
b/src/org/apache/xpath/compiler/FunctionTable.java index dfa19f14..cefc1b7b 100644
--- a/src/org/apache/xpath/compiler/FunctionTable.java
+++ b/src/org/apache/xpath/compiler/FunctionTable.java
@@ -152,6 +152,9 @@ public class FunctionTable
   
   /** The 'tokenize()' id. */
   public static final int FUNC_TOKENIZE = 43;
+  
+  /** The 'unparsed-text()' id. */
+  public static final int FUNC_UNPARSED_TEXT = 44;
 
   // Proprietary
 
@@ -180,7 +183,7 @@ public class FunctionTable
    * Number of built in functions. Be sure to update this as
    * built-in functions are added.
    */
-  private static final int NUM_BUILT_IN_FUNCS = 44;
+  private static final int NUM_BUILT_IN_FUNCS = 45;
 
   /**
    * Number of built-in functions that may be added.
@@ -260,6 +263,8 @@ public class FunctionTable
       org.apache.xalan.templates.FuncRegexGroup.class;
     m_functions[FUNC_TOKENIZE] = 
       org.apache.xpath.functions.FuncTokenize.class;
+    m_functions[FUNC_UNPARSED_TEXT] = 
+      org.apache.xpath.functions.FuncUnparsedText.class;
   }
 
   static{
@@ -347,6 +352,8 @@ public class FunctionTable
                           new Integer(FunctionTable.FUNC_REGEX_GROUP));
           m_functionID.put(Keywords.FUNC_TOKENIZE,
                           new Integer(FunctionTable.FUNC_TOKENIZE));
+          m_functionID.put(Keywords.FUNC_UNPARSED_TEXT,
+                          new Integer(FunctionTable.FUNC_UNPARSED_TEXT));
   }
   
   public FunctionTable(){
diff --git a/src/org/apache/xpath/compiler/Keywords.java \
b/src/org/apache/xpath/compiler/Keywords.java index d303646f..1ebfaec8 100644
--- a/src/org/apache/xpath/compiler/Keywords.java
+++ b/src/org/apache/xpath/compiler/Keywords.java
@@ -228,6 +228,9 @@ public class Keywords
   
   /** tokenize function string. */
   public static final String FUNC_TOKENIZE = "tokenize";
+  
+  /** unparsed-text function string. */
+  public static final String FUNC_UNPARSED_TEXT = "unparsed-text";
 
   // Proprietary, built in functions
 
diff --git a/src/org/apache/xpath/functions/FuncConcat.java \
b/src/org/apache/xpath/functions/FuncConcat.java index 4099225c..6c46f245 100644
--- a/src/org/apache/xpath/functions/FuncConcat.java
+++ b/src/org/apache/xpath/functions/FuncConcat.java
@@ -20,13 +20,18 @@
  */
 package org.apache.xpath.functions;
 
+import javax.xml.transform.TransformerException;
+
 import org.apache.xalan.res.XSLMessages;
+import org.apache.xpath.Expression;
 import org.apache.xpath.XPathContext;
+import org.apache.xpath.axes.SelfIteratorNoPredicate;
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XString;
 
 /**
- * Execute the Concat() function.
+ * Execute the concat() function.
+ * 
  * @xsl.usage advanced
  */
 public class FuncConcat extends FunctionMultiArgs
@@ -34,8 +39,9 @@ public class FuncConcat extends FunctionMultiArgs
     static final long serialVersionUID = 1737228885202314413L;
 
   /**
-   * 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.
    *
@@ -44,21 +50,20 @@ public class FuncConcat extends FunctionMultiArgs
   public XObject execute(XPathContext xctxt) throws \
javax.xml.transform.TransformerException  {
 
-    StringBuffer sb = new StringBuffer();
+    StringBuffer sb = new StringBuffer();        
 
     // Compiler says we must have at least two arguments.
-    sb.append(m_arg0.execute(xctxt).str());
-    sb.append(m_arg1.execute(xctxt).str());
+    sb.append(inspectSelfAxesExpression(m_arg0, xctxt));
+    sb.append(inspectSelfAxesExpression(m_arg1, xctxt));
 
-    if (null != m_arg2)
-      sb.append(m_arg2.execute(xctxt).str());
+    if (m_arg2 != null) {
+       sb.append(inspectSelfAxesExpression(m_arg2, xctxt));
+    }
 
-    if (null != m_args)
-    {
-      for (int i = 0; i < m_args.length; i++)
-      {
-        sb.append(m_args[i].execute(xctxt).str());
-      }
+    if (m_args != null) {
+       for (int i = 0; i < m_args.length; i++) {
+         sb.append(inspectSelfAxesExpression(m_args[i], xctxt));
+       }
     }
 
     return new XString(sb.toString());
@@ -87,4 +92,29 @@ public class FuncConcat extends FunctionMultiArgs
   protected void reportWrongNumberArgs() throws WrongNumberArgsException {
       throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("gtone", \
null));  }
+  
+  /*
+   * If the expression's pattern string is ".", the evaluation result of expression,
+   * is the string value of XPath context item.
+   */
+  private String inspectSelfAxesExpression(Expression expr, XPathContext xctxt) 
+                                                                   throws \
TransformerException { +      String resultStr = null;
+      
+      XObject xpath3ContextItem = xctxt.getXPath3ContextItem();
+      if (expr instanceof SelfIteratorNoPredicate) {
+          if (xpath3ContextItem != null) {
+              resultStr = xpath3ContextItem.str();
+          }
+          else {
+              resultStr = expr.execute(xctxt).str();   
+          }
+      }
+      else {
+          resultStr = expr.execute(xctxt).str(); 
+      }
+      
+      return resultStr;
+      
+  }
 }
diff --git a/src/org/apache/xpath/functions/FuncUnparsedText.java \
b/src/org/apache/xpath/functions/FuncUnparsedText.java new file mode 100644
index 00000000..334c31f3
--- /dev/null
+++ b/src/org/apache/xpath/functions/FuncUnparsedText.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xpath.functions;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import javax.xml.transform.SourceLocator;
+
+import org.apache.xalan.res.XSLMessages;
+import org.apache.xml.utils.XMLString;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XString;
+import org.apache.xpath.res.XPATHErrorResources;
+
+/**
+ * Execute the unparsed-text() function.
+ * 
+ * This function is designed, to read from an external resource (for example, a \
file)  + * and returns a string representation of the resource.
+ * 
+ * @author Mukul Gandhi <mukulg@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FuncUnparsedText extends Function2Args {
+  
+  private static final long serialVersionUID = 1760543978696171233L;
+    
+  private static final String FUNCTION_NAME = "unparsed-text()"; 
+
+  /**
+   * Execute the function. The function must return a valid object.
+   * 
+   * @param xctxt The current execution context.
+   * @return A valid XObject.
+   *
+   * @throws javax.xml.transform.TransformerException
+   */
+  public XObject execute(XPathContext xctxt) throws \
javax.xml.transform.TransformerException +  {      
+      XObject result = null;
+      
+      SourceLocator srcLocator = xctxt.getSAXLocator();
+        
+      XMLString href = m_arg0.execute(xctxt).xstr();
+      
+      String encodingStr = null;
+        
+      if (m_arg1 != null) {
+         XMLString encoding = m_arg1.execute(xctxt).xstr();
+         encodingStr = encoding.toString();
+         if (!("utf-8".equalsIgnoreCase(encodingStr) || \
"utf-16".equalsIgnoreCase(encodingStr))) { +             throw new \
javax.xml.transform.TransformerException("FOUT1190 : The value of the 'encoding' \
argument " +                                                   + "is not a valid \
encoding name. Allowed encoding names are " +                                         \
+ "UTF-8 and UTF-16.", srcLocator);     +         }
+      }
+        
+      try {
+          String urlContents = readDataFromUrl(new URL(href.toString()), \
encodingStr); +          String resultStr = null;
+          if (encodingStr != null) {
+              resultStr = new String(urlContents.getBytes(), \
encodingStr.toUpperCase());               +          }
+          else {
+              resultStr = urlContents;  
+          }
+          
+          result = new XString(resultStr);
+      }
+      catch (IOException ex) {
+          throw new javax.xml.transform.TransformerException(ex.getMessage(), \
srcLocator);   +      }
+        
+      return result;
+
+  }
+  
+  
+
+  /**
+   * Check that the number of arguments passed to this function is correct.
+   *
+   * @param argNum The number of arguments that is being passed to the function.
+   *
+   * @throws WrongNumberArgsException
+   */
+  public void checkNumberArgs(int argNum) throws WrongNumberArgsException
+  {
+     if (argNum > 2) {
+        reportWrongNumberArgs();
+     }
+  }
+
+  /**
+   * Constructs and throws a WrongNumberArgException with the appropriate
+   * message for this function object.
+   *
+   * @throws WrongNumberArgsException
+   */
+  protected void reportWrongNumberArgs() throws WrongNumberArgsException {
+      throw new WrongNumberArgsException(XSLMessages.createXPATHMessage(
+                                              XPATHErrorResources.ER_ONE_OR_TWO, \
null)); //"1 or 2" +  }
+  
+  /*
+   * Read the string contents from a url.
+   */
+  private String readDataFromUrl(URL url, String encodingStr) throws IOException {
+      StringBuilder sb = new StringBuilder();
+      String inpLine;
+      
+      InputStream inpStream = url.openStream();
+      
+      try {                    
+          BufferedReader buffReader = new BufferedReader(new \
InputStreamReader(inpStream)); +          int chr;
+          while ((chr = buffReader.read()) != -1) {
+             sb.append((char)chr);
+          }
+      } finally {
+          inpStream.close();
+      }
+   
+      return sb.toString();
+  }
+  
+}
diff --git a/src/org/apache/xpath/res/XPATHErrorResources.java \
b/src/org/apache/xpath/res/XPATHErrorResources.java index 75af7bcb..8dd71cd2 100644
--- a/src/org/apache/xpath/res/XPATHErrorResources.java
+++ b/src/org/apache/xpath/res/XPATHErrorResources.java
@@ -228,6 +228,8 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
    /**  The FastStringBuffer argument can not be null   */
  public static final String ER_FASTSTRINGBUFFER_CANNOT_BE_NULL = 
 	 "ER_FASTSTRINGBUFFER_CANNOT_BE_NULL";
+  /** 1 or 2 */
+  public static final String ER_ONE_OR_TWO = "ER_ONE_OR_TWO";
    /**  2 or 3   */
   public static final String ER_TWO_OR_THREE = "ER_TWO_OR_THREE";
   /**  1, 2 or 3   */
@@ -622,6 +624,9 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
   { ER_FASTSTRINGBUFFER_CANNOT_BE_NULL,
       "The FastStringBuffer argument can not be null"},
 
+  { ER_ONE_OR_TWO,
+       "1 or 2"},
+  
   { ER_TWO_OR_THREE,
        "2 or 3"},
   


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xalan.apache.org
For additional commands, e-mail: commits-help@xalan.apache.org


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic