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/05/16 17:23:20 UTC

[xalan-java] branch xalan-j_xslt3.0 updated: committing implementation of xslt 3.0 instruction xsl:analyze-string. this is fairly complete, but is wip

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 3204b78e committing implementation of xslt 3.0 instruction xsl:analyze-string. this is fairly complete, but is wip
3204b78e is described below

commit 3204b78eda0a3e3e1158117615861dff46315185
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Tue May 16 22:52:29 2023 +0530

    committing implementation of xslt 3.0 instruction xsl:analyze-string. this is fairly complete, but is wip
---
 .../apache/xalan/processor/XSLTAttributeDef.java   |  28 +-
 src/org/apache/xalan/processor/XSLTSchema.java     |  59 +++-
 src/org/apache/xalan/templates/Constants.java      |  13 +-
 .../apache/xalan/templates/ElemAnalyzeString.java  | 327 +++++++++++++++++++++
 .../xalan/templates/ElemMatchingSubstring.java     | 173 +++++++++++
 .../xalan/templates/ElemNonMatchingSubstring.java  | 194 ++++++++++++
 src/org/apache/xml/dtm/DTMManager.java             |  35 +++
 .../xpath/functions/RegExFunctionSupport.java      |   2 +-
 8 files changed, 816 insertions(+), 15 deletions(-)

diff --git a/src/org/apache/xalan/processor/XSLTAttributeDef.java b/src/org/apache/xalan/processor/XSLTAttributeDef.java
index 07554134..cfb2c59c 100644
--- a/src/org/apache/xalan/processor/XSLTAttributeDef.java
+++ b/src/org/apache/xalan/processor/XSLTAttributeDef.java
@@ -41,8 +41,8 @@ import org.apache.xpath.XPath;
  
 /**
  * This class defines an attribute for an element in a XSLT stylesheet,
- * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the
- * mapping between Xalan classes and the markup attributes in the element.
+ * and is meant to reflect the structure defined at https://www.w3.org/TR/xslt-30/#xsd11-schema-for-xslt, 
+ * and the mapping between Xalan classes and the markup attributes in the element.
  */
 public class XSLTAttributeDef
 {
@@ -268,7 +268,10 @@ public class XSLTAttributeDef
   // Used for a list of white-space delimited strings.
   // strings are checked to make sure they are valid 
   // prefixes, and are not expanded when processed. 
-  T_PREFIXLIST = 20;
+  T_PREFIXLIST = 20,
+  
+  // Used for a string value.
+  T_STRING = 21;
 
   /** Representation for an attribute in a foreign namespace. */
   static final XSLTAttributeDef m_foreignAttr = new XSLTAttributeDef("*", "*",
@@ -1210,6 +1213,22 @@ public class XSLTAttributeDef
 
     return strings;
   }
+  
+  /**
+   * Process an attribute string of type T_STRING.
+   *
+   * @param handler        non-null reference to current StylesheetHandler that is constructing the Templates.
+   * @param uri            The Namespace URI, or an empty string.
+   * @param name           The local name (without prefix), or empty string if not namespace processing.
+   * @param rawName        The qualified name (with prefix).
+   * @param value          String value.
+   *
+   * @return String value itself.
+   */
+  String processSTRING(StylesheetHandler handler, String uri, String name, 
+                                                  String rawName, String value) {
+     return value;
+  }
 
   /**
    * Process an attribute string of type T_URLLIST into
@@ -1435,6 +1454,9 @@ public class XSLTAttributeDef
     case T_STRINGLIST :
       processedValue = processSTRINGLIST(handler, uri, name, rawName, value);
       break;
+    case T_STRING :
+      processedValue = processSTRING(handler, uri, name, rawName, value);
+      break;
     case T_PREFIX_URLLIST :
       processedValue = processPREFIX_URLLIST(handler, uri, name, rawName,
                                              value);
diff --git a/src/org/apache/xalan/processor/XSLTSchema.java b/src/org/apache/xalan/processor/XSLTSchema.java
index 7040cbd7..3faa0c65 100644
--- a/src/org/apache/xalan/processor/XSLTSchema.java
+++ b/src/org/apache/xalan/processor/XSLTSchema.java
@@ -23,6 +23,7 @@ package org.apache.xalan.processor;
 import java.util.HashMap;
 
 import org.apache.xalan.templates.Constants;
+import org.apache.xalan.templates.ElemAnalyzeString;
 import org.apache.xalan.templates.ElemApplyImport;
 import org.apache.xalan.templates.ElemApplyTemplates;
 import org.apache.xalan.templates.ElemAttribute;
@@ -41,7 +42,9 @@ import org.apache.xalan.templates.ElemForEach;
 import org.apache.xalan.templates.ElemForEachGroup;
 import org.apache.xalan.templates.ElemIf;
 import org.apache.xalan.templates.ElemLiteralResult;
+import org.apache.xalan.templates.ElemMatchingSubstring;
 import org.apache.xalan.templates.ElemMessage;
+import org.apache.xalan.templates.ElemNonMatchingSubstring;
 import org.apache.xalan.templates.ElemNumber;
 import org.apache.xalan.templates.ElemOtherwise;
 import org.apache.xalan.templates.ElemPI;
@@ -58,9 +61,10 @@ import org.apache.xalan.templates.ElemWithParam;
 import org.apache.xml.utils.QName;
 
 /**
- * This class defines the allowed structure for a stylesheet, and the
+ * This class defines the allowed structure for an XSLT stylesheet, and the
  * mapping between Xalan classes and the markup elements in the stylesheet.
- * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
+ * 
+ * @see <a href="https://www.w3.org/TR/xslt-30/#xsd11-schema-for-xslt">XSD 1.1 Schema for XSLT Stylesheets</a>
  */
 public class XSLTSchema extends XSLTElementDef
 {
@@ -74,8 +78,8 @@ public class XSLTSchema extends XSLTElementDef
   }
 
   /**
-   * This method builds an XSLT "schema" according to http://www.w3.org/TR/xslt#dtd.  This
-   * schema provides instructions for building the Xalan Stylesheet (Templates) structure.
+   * This method builds an XSLT "schema" according to https://www.w3.org/TR/xslt-30/#xsd11-schema-for-xslt.
+   * This schema provides instructions for building the Xalan Stylesheet (Templates) structure.
    */
   void build()
   {
@@ -193,11 +197,23 @@ public class XSLTSchema extends XSLTElementDef
       
       
     // Required.                                       
-    // xsl:value-of, xsl:for-each, xsl:copy-of, xsl:for-each-group                             
+    // xsl:value-of, xsl:for-each, xsl:copy-of, xsl:for-each-group, xsl:analyze-string                             
     XSLTAttributeDef selectAttrRequired = new XSLTAttributeDef(null,
                                             "select",
                                             XSLTAttributeDef.T_EXPR, true, false, XSLTAttributeDef.ERROR);
     
+    // Required.                                       
+    // xsl:analyze-string                             
+    XSLTAttributeDef regexAttrRequired = new XSLTAttributeDef(null,
+                                              "regex",
+                                              XSLTAttributeDef.T_STRING, true, false, XSLTAttributeDef.ERROR);
+    
+    // Optional.                                       
+    // xsl:analyze-string                              
+    XSLTAttributeDef flagsAttrOpt = new XSLTAttributeDef(null,
+                                             "flags",
+                                             XSLTAttributeDef.T_STRING, false, false, XSLTAttributeDef.ERROR);
+    
     // Optional.                                       
     // xsl:for-each-group                             
     XSLTAttributeDef groupByAttrOpt = new XSLTAttributeDef(null,
@@ -368,11 +384,11 @@ public class XSLTSchema extends XSLTElementDef
       new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "*",
                            XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING);
                            
-    XSLTElementDef[] templateElements = new XSLTElementDef[24];
-    XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[25];
-    XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[25];
+    XSLTElementDef[] templateElements = new XSLTElementDef[27];
+    XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[28];
+    XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[28];
     //exslt
-    XSLTElementDef[] exsltFunctionElements = new XSLTElementDef[25];
+    XSLTElementDef[] exsltFunctionElements = new XSLTElementDef[28];
     
     XSLTElementDef[] charTemplateElements = new XSLTElementDef[16];
     XSLTElementDef resultElement = new XSLTElementDef(this, null, "*",
@@ -479,6 +495,28 @@ public class XSLTSchema extends XSLTElementDef
                                              new ProcessorTemplateElem(),
                                              ElemForEachGroup.class /* class object */, true, false, true, 20, true);
     
+    XSLTElementDef xslAnalyzeString = new XSLTElementDef(this,
+                                                Constants.S_XSLNAMESPACEURL, "analyze-string",
+                                                null /*alias */, templateElements,
+                                                new XSLTAttributeDef[]{ selectAttrRequired, 
+                                                                        regexAttrRequired, flagsAttrOpt, spaceAttr }, 
+                                                new ProcessorTemplateElem(),
+                                                ElemAnalyzeString.class /* class object */, true, false, true, 20, true);
+    
+    XSLTElementDef xslMatchingSubstring = new XSLTElementDef(this,
+                                                Constants.S_XSLNAMESPACEURL, "matching-substring",
+                                                null /*alias */, templateElements,
+                                                new XSLTAttributeDef[] { }, 
+                                                new ProcessorTemplateElem(),
+                                                ElemMatchingSubstring.class /* class object */, true, false, true, 20, true);
+    
+    XSLTElementDef xslNonMatchingSubstring = new XSLTElementDef(this,
+                                                Constants.S_XSLNAMESPACEURL, "non-matching-substring",
+                                                null /*alias */, templateElements,
+                                                new XSLTAttributeDef[] { }, 
+                                                new ProcessorTemplateElem(),
+                                                ElemNonMatchingSubstring.class /* class object */, true, false, true, 20, true);
+    
     XSLTElementDef xslIf = new XSLTElementDef(this,
                                               Constants.S_XSLNAMESPACEURL,
                                               "if", null /*alias */,
@@ -629,6 +667,9 @@ public class XSLTSchema extends XSLTElementDef
     templateElements[i++] = xslApplyImports;
     templateElements[i++] = xslForEach;
     templateElements[i++] = xslForEachGroup;
+    templateElements[i++] = xslAnalyzeString;
+    templateElements[i++] = xslMatchingSubstring;
+    templateElements[i++] = xslNonMatchingSubstring;
     templateElements[i++] = xslValueOf;
     templateElements[i++] = xslCopyOf;
     templateElements[i++] = xslNumber;
diff --git a/src/org/apache/xalan/templates/Constants.java b/src/org/apache/xalan/templates/Constants.java
index 8545fe85..83692489 100644
--- a/src/org/apache/xalan/templates/Constants.java
+++ b/src/org/apache/xalan/templates/Constants.java
@@ -88,9 +88,15 @@ public class Constants extends org.apache.xml.utils.Constants
   ELEMNAME_EXTENSIONSCRIPT = 86, ELEMNAME_OUTPUT = 80,
   ELEMNAME_COMPONENT = 81, ELEMNAME_SCRIPT = 82,
   
-  ELEMNAME_FOREACHGROUP = 90;
+  ELEMNAME_FOREACHGROUP = 90,
 
-  // Next free number: 91
+  ELEMNAME_ANALYZESTRING = 91,
+  
+  ELEMNAME_MATCHING_SUBSTRING = 92,
+  
+  ELEMNAME_NON_MATCHING_SUBSTRING = 93;
+  
+  // next available number : 94
 
   /**
    * Literals for XSL element names. Note that there are more
@@ -132,6 +138,9 @@ public class Constants extends org.apache.xml.utils.Constants
       ELEMNAME_FALLBACK_STRING = "fallback",
       ELEMNAME_FOREACH_STRING = "for-each",
       ELEMNAME_FOREACHGROUP_STRING = "for-each-group",
+      ELEMNAME_ANALYZESTRING_STRING = "analyze-string",
+      ELEMNAME_MATCHINGSUBSTRING_STRING = "matching-substring",
+      ELEMNAME_NONMATCHINGSUBSTRING_STRING = "non-matching-substring",
       ELEMNAME_IF_STRING = "if",
       ELEMNAME_IMPORT_STRING = "import",
       ELEMNAME_INCLUDE_STRING = "include",
diff --git a/src/org/apache/xalan/templates/ElemAnalyzeString.java b/src/org/apache/xalan/templates/ElemAnalyzeString.java
new file mode 100644
index 00000000..668e75c2
--- /dev/null
+++ b/src/org/apache/xalan/templates/ElemAnalyzeString.java
@@ -0,0 +1,327 @@
+/*
+ * 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.xalan.templates;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.transformer.TransformerImpl;
+import org.apache.xpath.Expression;
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.functions.RegExFunctionSupport;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.regex.Matcher;
+
+/**
+ * XSLT 3.0 analyze-string element.
+ * 
+ * <xsl:analyze-string
+            select = expression
+            regex = { string }
+            flags? = { string } >
+       <!-- Content: (xsl:matching-substring?, xsl:non-matching-substring?, xsl:fallback*) -->
+   </xsl:analyze-string>
+   
+   <xsl:matching-substring>
+      <!-- Content: sequence-constructor -->
+   </xsl:matching-substring>
+   
+   <xsl:non-matching-substring>
+      <!-- Content: sequence-constructor -->
+   </xsl:non-matching-substring>
+   
+ *  
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+
+/*
+ * Implementation of the XSLT 3.0 xsl:analyze-string instruction.
+ * 
+ * This XSLT instruction is intended to process, all the 'non overlapping' substrings 
+ * of the input string that match the provided regular expression.
+ * 
+ * The XSLT function fn:regex-group may be used optionally along with XSLT instruction 
+ * xsl:analyze-string.    // revisit
+ * 
+ * With xsl:analyze-string element, we're presently not implementing xsl:fallback 
+ * elements. xsl:fallback elements don't have much useful use cases, within 
+ * xsl:analyze-string element.   // revisit 
+ * 
+ */
+public class ElemAnalyzeString extends ElemTemplateElement implements ExpressionOwner {
+  
+  private static final long serialVersionUID = 5892915527446791252L;
+
+  /**
+   * Constructor of this class.
+   */
+  public ElemAnalyzeString() {}
+
+  /**
+   * The "select" expression.
+   */
+  protected Expression m_selectExpression = null;
+  
+  /**
+   * The "regex" expression.
+  */
+  protected String m_regex = null;
+  
+  /**
+   * The regex "flags" expression.
+  */
+  protected String m_flags = null;
+
+  /**
+   * Set the "select" attribute.
+   *
+   * @param xpath The XPath expression for the "select" attribute.
+   */
+  public void setSelect(XPath xpath) {
+      m_selectExpression = xpath.getExpression();   
+  }
+
+  /**
+   * Get the "select" attribute.
+   *
+   * @return The XPath expression for the "select" attribute.
+   */
+  public Expression getSelect() {
+      return m_selectExpression;
+  }
+  
+  /**
+   * Set the "regex" attribute.
+   *
+   * @param regex The string value for the "regex" attribute.
+   */
+  public void setRegex(String regex) {
+      m_regex = regex;   
+  }
+
+  /**
+   * Get the "regex" attribute.
+   *
+   * @return The string value for the "regex" attribute.
+   */
+  public String getRegex() {
+      return m_regex;
+  }
+  
+  /**
+   * Set the "flags" attribute.
+   *
+   * @param regex The string value for the "flags" attribute.
+   */
+  public void setFlags(String flags) {
+      m_flags = flags;   
+  }
+
+  /**
+   * Get the "flags" attribute.
+   *
+   * @return The string value for the "flags" attribute.
+   */
+  public String getFlags() {
+      return m_flags;
+  }
+
+  /**
+   * This function is called after everything else has been
+   * recomposed, and allows the template to set remaining
+   * values that may be based on some other property that
+   * depends on recomposition.
+   *
+   * @throws TransformerException
+   */
+  public void compose(StylesheetRoot sroot) throws TransformerException {
+        
+        super.compose(sroot);
+    
+        java.util.Vector vnames = sroot.getComposeState().getVariableNames();
+    
+        if (null != m_selectExpression) {
+            m_selectExpression.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize());
+        }
+        else {
+            m_selectExpression = getStylesheetRoot().m_selectDefault.getExpression();
+        }
+  }
+  
+  /**
+   * This after the template's children have been composed.
+   */
+  public void endCompose(StylesheetRoot sroot) throws TransformerException {   
+      super.endCompose(sroot);
+  }
+
+  /**
+   * Get an int constant identifying the type of element.
+   *
+   * @return The token ID for this element
+   */
+  public int getXSLToken() {
+      return Constants.ELEMNAME_ANALYZESTRING;
+  }
+
+  /**
+   * Return the node name.
+   *
+   * @return The element's name
+   */
+  public String getNodeName() {
+      return Constants.ELEMNAME_ANALYZESTRING_STRING;
+  }
+
+  /**
+   * Execute the XSLT element xsl:analyze-string's transformation.
+   *
+   * @param transformer non-null reference to the the current transform-time state.
+   *
+   * @throws TransformerException
+   */
+  public void execute(TransformerImpl transformer) throws TransformerException {
+      transformSelectedNodes(transformer);
+  }
+
+  /**
+   * Get template element associated with this.
+   * 
+   * @return template element associated with this (itself)
+   */
+  protected ElemTemplateElement getTemplateMatch() {
+      return this;
+  }
+
+  /**
+   *
+   * @param transformer non-null reference to the the current transform-time state.
+   *
+   * @throws TransformerException Thrown in a variety of circumstances.
+   * 
+   * @xsl.usage advanced
+   */
+  public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {
+      
+       final XPathContext xctxt = transformer.getXPathContext();
+       
+       XObject xpathEvalResult = m_selectExpression.execute(xctxt);
+       
+       String strToBeAnalyzed = xpathEvalResult.str();
+       
+       long currentTimeMills = System.currentTimeMillis();
+       String tempReplStr = (Long.valueOf(currentTimeMills)).toString();
+       
+       if (m_flags != null && !RegExFunctionSupport.isFlagStrValid(m_flags)) {
+           throw new javax.xml.transform.TransformerException("XTDE1145 : Invalid regular expression flags are present, with "
+                                                                                     + "xsl:analyze-string element.", xctxt.getSAXLocator());    
+       }
+       
+       Matcher regexMatcher = RegExFunctionSupport.compileAndExecute(RegExFunctionSupport.trfPatternStrForSubtraction(
+                                                                                             m_regex), m_flags, strToBeAnalyzed);       
+       String tempReplacedStr = regexMatcher.replaceAll(tempReplStr);
+       
+       ElemTemplateElement templateElem1 = this.m_firstChild;
+       ElemTemplateElement templateElem2 = null;
+       ElemTemplateElement templateElem3 = null;
+       
+       if (templateElem1 == null) {
+           throw new javax.xml.transform.TransformerException("XTSE1130 : At least one of the elements xsl:matching-substring or "
+                                                                  + "xsl:non-matching-substring must be present within xsl:analyze-string "
+                                                                  + "element.", xctxt.getSAXLocator());    
+       }
+       else {
+           templateElem2 = templateElem1.m_nextSibling;
+           if (templateElem2 != null) {
+               if (!((templateElem1 instanceof ElemMatchingSubstring) && (templateElem2 instanceof ElemNonMatchingSubstring))) {
+                   throw new javax.xml.transform.TransformerException("XTSE0010 : xsl:matching-substring element must come first within "
+                                                                                          + "xsl:analyze-string element.", xctxt.getSAXLocator());   
+               }
+               templateElem3 = templateElem2.m_nextSibling;
+               if (templateElem3 != null) {
+                   throw new javax.xml.transform.TransformerException("XTSE0010 : Only xsl:matching-substring and xsl:non-matching-substring "
+                                                                                              + "elements are allowed within xsl:analyze-string "
+                                                                                              + "element.", xctxt.getSAXLocator());    
+               }
+           }
+       }
+       
+       String[] strParts = tempReplacedStr.split(tempReplStr);
+       for (int idx = 0; idx < strParts.length; idx++) {           
+           if (templateElem2 != null) {
+               ((ElemNonMatchingSubstring)templateElem2).setStrValue(strParts[idx]);               
+               xctxt.setSAXLocator(templateElem2);
+               transformer.setCurrentElement(templateElem2);                   
+               templateElem2.execute(transformer);
+           }
+           
+           // ((ElemMatchingSubstring)templateElem1).setStrValue("???");   // revisit
+           xctxt.setSAXLocator(templateElem1);
+           transformer.setCurrentElement(templateElem1);                   
+           templateElem1.execute(transformer);
+       }
+       
+  }
+
+  /**
+   *
+   * @param newChild Child to add to child list
+   *
+   * @return Child just added to child list
+   */
+  public ElemTemplateElement appendChild(ElemTemplateElement newChild)
+  {
+      return super.appendChild(newChild);
+  }
+  
+  /**
+   * Call the children visitors.
+   * 
+   * @param visitor The visitor whose appropriate method will be called.
+   */
+  public void callChildVisitors(XSLTVisitor visitor, boolean callAttributes)
+  {
+  	  if (callAttributes && (null != m_selectExpression)) {
+  		 m_selectExpression.callVisitors(this, visitor);
+  	  }
+
+      super.callChildVisitors(visitor, callAttributes);
+  }
+
+  /**
+   * @see ExpressionOwner#getExpression()
+   */
+  public Expression getExpression() {
+      return m_selectExpression;
+  }
+
+  /**
+   * @see ExpressionOwner#setExpression(Expression)
+   */
+  public void setExpression(Expression exp) {
+      exp.exprSetParent(this);
+      m_selectExpression = exp;
+  }
+  
+}
diff --git a/src/org/apache/xalan/templates/ElemMatchingSubstring.java b/src/org/apache/xalan/templates/ElemMatchingSubstring.java
new file mode 100644
index 00000000..774ea943
--- /dev/null
+++ b/src/org/apache/xalan/templates/ElemMatchingSubstring.java
@@ -0,0 +1,173 @@
+/*
+ * 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.xalan.templates;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.transformer.TransformerImpl;
+import org.apache.xpath.Expression;
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPathContext;
+
+/**
+   XSLT 3.0 matching-substring element.
+   
+   <xsl:matching-substring>
+      <!-- Content: sequence-constructor -->
+   </xsl:matching-substring>
+   
+   @author Mukul Gandhi <mu...@apache.org>
+  
+ * @xsl.usage advanced
+ */
+
+/*
+ * Implementation of the XSLT 3.0 xsl:matching-substring instruction.
+ * 
+ * This XSLT element can only be used within the element xsl:analyze-string.
+ * 
+ */
+public class ElemMatchingSubstring extends ElemTemplateElement implements ExpressionOwner {
+  
+  private static final long serialVersionUID = -5675647188821169056L;
+  
+  private String m_strValue = null;
+
+  /**
+   * Constructor of this class.
+   */
+  public ElemMatchingSubstring(){}
+
+  /**
+   * This function is called after everything else has been
+   * recomposed, and allows the template to set remaining
+   * values that may be based on some other property that
+   * depends on recomposition.
+   *
+   * @throws TransformerException
+   */
+  public void compose(StylesheetRoot sroot) throws TransformerException {
+      super.compose(sroot);
+  }
+  
+  /**
+   * This after the template's children have been composed.
+   */
+  public void endCompose(StylesheetRoot sroot) throws TransformerException {
+      super.endCompose(sroot);
+  }
+
+  /**
+   * Get an int constant identifying the type of element.
+   * @see org.apache.xalan.templates.Constants
+   *
+   * @return The token ID for this element
+   */
+  public int getXSLToken() {
+     return Constants.ELEMNAME_MATCHING_SUBSTRING;
+  }
+
+  /**
+   * Return the node name.
+   *
+   * @return The element's name
+   */
+  public String getNodeName() {
+     return Constants.ELEMNAME_MATCHINGSUBSTRING_STRING;
+  }
+
+  /**
+   * Execute the xsl:matching-substring transformation
+   *
+   * @param transformer non-null reference to the the current transform-time state.
+   *
+   * @throws TransformerException
+   */
+  public void execute(TransformerImpl transformer) throws TransformerException {
+      transformSelectedNodes(transformer);
+  }
+
+  /**
+   * Get template element associated with this
+   *
+   * @return template element associated with this (itself)
+   */
+  protected ElemTemplateElement getTemplateMatch() {
+      return this;
+  }
+
+  /**
+   * @param transformer             non-null reference to the the current transform-time state.
+   *
+   * @throws TransformerException   Thrown in a variety of circumstances.
+   * 
+   * @xsl.usage advanced
+   */
+  public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {
+
+      final XPathContext xctxt = transformer.getXPathContext();
+       
+      for (ElemTemplateElement elem = this.m_firstChild; elem != null; 
+                                                    elem = elem.m_nextSibling) {
+          xctxt.setSAXLocator(elem);
+          transformer.setCurrentElement(elem);
+          elem.execute(transformer);
+      }
+  }
+
+  /**
+
+   * @param newChild Child to add to child list
+   *
+   * @return Child just added to child list
+   */
+  public ElemTemplateElement appendChild(ElemTemplateElement newChild) {
+      return super.appendChild(newChild);
+  }
+  
+  /**
+   * Call the children visitors.
+   * 
+   * @param visitor The visitor whose appropriate method will be called.
+   */
+  public void callChildVisitors(XSLTVisitor visitor, boolean callAttributes) {
+      super.callChildVisitors(visitor, callAttributes);
+  }
+
+  @Override
+  public Expression getExpression() {
+      return null;
+  }
+
+  @Override
+  public void setExpression(Expression exp) {
+      // NO OP 
+  }
+
+  public String getStrValue() {
+      return m_strValue;
+  }
+
+  public void setStrValue(String m_strValue) {
+      this.m_strValue = m_strValue;
+  }
+
+}
diff --git a/src/org/apache/xalan/templates/ElemNonMatchingSubstring.java b/src/org/apache/xalan/templates/ElemNonMatchingSubstring.java
new file mode 100644
index 00000000..7a810e31
--- /dev/null
+++ b/src/org/apache/xalan/templates/ElemNonMatchingSubstring.java
@@ -0,0 +1,194 @@
+/*
+ * 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.xalan.templates;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.xalan.transformer.TransformerImpl;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xpath.Expression;
+import org.apache.xpath.ExpressionOwner;
+import org.apache.xpath.XPathContext;
+
+/**
+   XSLT 3.0 non-matching-substring element.
+   
+   <xsl:non-matching-substring>
+      <!-- Content: sequence-constructor -->
+   </xsl:non-matching-substring>
+ 
+   @author Mukul Gandhi <mu...@apache.org>
+   
+ * @xsl.usage advanced
+ */
+
+/*
+ * Implementation of the XSLT 3.0 xsl:non-matching-substring instruction.
+ * 
+ * This XSLT element can only be used within the element xsl:analyze-string.
+ * 
+ */
+public class ElemNonMatchingSubstring extends ElemTemplateElement implements ExpressionOwner {
+
+  private static final long serialVersionUID = -3993288598365914097L;
+  
+  private String m_strValue = null;
+
+  /**
+    * Constructor of this class.
+  */
+  public ElemNonMatchingSubstring(){}
+
+  /**
+   * This function is called after everything else has been
+   * recomposed, and allows the template to set remaining
+   * values that may be based on some other property that
+   * depends on recomposition.
+   *
+   * @throws TransformerException
+   */
+  public void compose(StylesheetRoot sroot) throws TransformerException {
+      super.compose(sroot);
+  }
+  
+  /**
+   * This after the template's children have been composed.
+   */
+  public void endCompose(StylesheetRoot sroot) throws TransformerException {
+      super.endCompose(sroot);
+  }
+
+  /**
+   * Get an int constant identifying the type of element.
+   * @see org.apache.xalan.templates.Constants
+   *
+   * @return The token ID for this element
+   */
+  public int getXSLToken() {
+      return Constants.ELEMNAME_NON_MATCHING_SUBSTRING;
+  }
+
+  /**
+   * Return the node name.
+   *
+   * @return The element's name
+   */
+  public String getNodeName() {
+      return Constants.ELEMNAME_NONMATCHINGSUBSTRING_STRING;
+  }
+
+  /**
+   * Execute the non-matching-substring transformation.
+   *
+   * @param transformer non-null reference to the the current transform-time state.
+   *
+   * @throws TransformerException
+   */
+  public void execute(TransformerImpl transformer) throws TransformerException {
+      transformSelectedNodes(transformer);
+  }
+
+  /**
+   * Get template element associated with this.
+   *
+   * @return template element associated with this (itself)
+   */
+  protected ElemTemplateElement getTemplateMatch() {
+      return this;
+  }
+
+  /**
+   *
+   * @param transformer                non-null reference to the the current transform-time state.
+   *
+   * @throws TransformerException      Thrown in a variety of circumstances.
+   * 
+   * @xsl.usage advanced
+   */
+  public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {
+
+      final XPathContext xctxt = transformer.getXPathContext();
+      
+      String strValueTobeEvaluated = getStrValue();
+      
+      XPathContext xctxtNew = new XPathContext(false);
+
+      DTMManager dtmMgr = xctxtNew.getDTMManager();      
+      DTM docFragDtm = dtmMgr.createDTMForSimpleXMLDocument(strValueTobeEvaluated);
+      
+      int contextNode = docFragDtm.getFirstChild(docFragDtm.getDocument());
+      
+      for (ElemTemplateElement elem = this.m_firstChild; elem != null;
+                                                           elem = elem.m_nextSibling) {
+          xctxtNew.pushCurrentNode(contextNode);
+          xctxtNew.setSAXLocator(elem);
+          transformer.setXPathContext(xctxtNew);          
+          transformer.setCurrentElement(elem);
+          elem.execute(transformer);
+      }
+      
+      // restore the XPath context to where that was, before this method was called
+      transformer.setXPathContext(xctxt);
+  }
+
+  /**
+   *
+   * @param newChild Child to add to child list
+   *
+   * @return Child just added to child list
+   */
+  public ElemTemplateElement appendChild(ElemTemplateElement newChild) {
+      return super.appendChild(newChild);
+  }
+  
+  /**
+   * Call the children visitors.
+   * 
+   * @param visitor The visitor whose appropriate method will be called.
+   */
+  public void callChildVisitors(XSLTVisitor visitor, boolean callAttributes) {
+      super.callChildVisitors(visitor, callAttributes);
+  }
+
+  /**
+   * @see ExpressionOwner#getExpression()
+   */
+  public Expression getExpression() {
+      return null;
+  }
+
+  /**
+   * @see ExpressionOwner#setExpression(Expression)
+   */
+  public void setExpression(Expression exp) {
+  	  // NO OP
+  }
+  
+  public String getStrValue() {
+      return m_strValue;
+  }
+
+  public void setStrValue(String m_strValue) {
+      this.m_strValue = m_strValue;
+  }
+  
+}
diff --git a/src/org/apache/xml/dtm/DTMManager.java b/src/org/apache/xml/dtm/DTMManager.java
index ac468fd3..771cf387 100644
--- a/src/org/apache/xml/dtm/DTMManager.java
+++ b/src/org/apache/xml/dtm/DTMManager.java
@@ -20,10 +20,17 @@
  */
 package org.apache.xml.dtm;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.dom.DOMSource;
+
 import org.apache.xml.res.XMLErrorResources;
 import org.apache.xml.res.XMLMessages;
 import org.apache.xml.utils.PrefixResolver;
 import org.apache.xml.utils.XMLStringFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
 
 /**
  * A DTMManager instance can be used to create DTM and
@@ -208,6 +215,34 @@ public abstract class DTMManager
    * @return a non-null DTM reference.
    */
   public abstract DTM createDocumentFragment();
+  
+  /*
+   * This method has been defined, to construct a DTM object, representing an
+   * XML document that contains only 'one xml element with a text node child'.
+   * This method currently supports, evaluation of XSLT xsl:analyze-string 
+   * instruction.
+   */
+  public DTM createDTMForSimpleXMLDocument(String strVal) {    
+        try {
+          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+    
+          dbf.setNamespaceAware(true);
+    
+          DocumentBuilder db = dbf.newDocumentBuilder();
+          Document doc = db.newDocument();
+          // "temp" is an arbitrary name selected for an XML element,
+          // for this purpose.
+          Element elem = doc.createElement("temp");
+          Text textNode = doc.createTextNode(strVal);
+          elem.appendChild(textNode);
+          doc.appendChild(elem);
+    
+          return getDTM(new DOMSource(doc), true, null, false, false);
+        }
+        catch (Exception e) {
+            throw new DTMException(e);
+        }
+  }
 
   /**
    * Release a DTM either to a lru pool, or completely remove reference.
diff --git a/src/org/apache/xpath/functions/RegExFunctionSupport.java b/src/org/apache/xpath/functions/RegExFunctionSupport.java
index 0f0f25c3..0783424a 100644
--- a/src/org/apache/xpath/functions/RegExFunctionSupport.java
+++ b/src/org/apache/xpath/functions/RegExFunctionSupport.java
@@ -75,7 +75,7 @@ public class RegExFunctionSupport {
        return flagStrValid; 
 	}
 	
-	private static Matcher compileAndExecute(String pattern, String flags, String src) {
+	public static Matcher compileAndExecute(String pattern, String flags, String src) {
 		int flag = Pattern.UNIX_LINES;
 		
 		if (flags != null) {			


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