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/12/30 12:10:04 UTC

(xalan-java) branch xalan-j_xslt3.0 updated: committing implementation of xpath 3.1 fn:deep-equal function, along with few related working test cases as well

This is an automated email from the ASF dual-hosted git repository.

mukulg pushed a commit to branch xalan-j_xslt3.0
in repository https://gitbox.apache.org/repos/asf/xalan-java.git


The following commit(s) were added to refs/heads/xalan-j_xslt3.0 by this push:
     new 4fee2540 committing implementation of xpath 3.1 fn:deep-equal function, along with few related working test cases as well
     new cabb81d7 Merge pull request #146 from mukulga/xalan-j_xslt3.0_mukul
4fee2540 is described below

commit 4fee2540532e193342b9c3f4fe4bfeb8cff398ab
Author: Mukul Gandhi <ga...@gmail.com>
AuthorDate: Sat Dec 30 17:36:28 2023 +0530

    committing implementation of xpath 3.1 fn:deep-equal function, along with few related working test cases as well
---
 src/org/apache/xpath/compiler/FunctionTable.java   |   8 +-
 src/org/apache/xpath/compiler/Keywords.java        |   3 +
 src/org/apache/xpath/functions/FuncDeepEqual.java  | 124 ++++++++++++
 src/org/apache/xpath/objects/XNodeSet.java         | 216 ++++++++++++++++++++-
 tests/fn_deep_equal/gold/test1.out                 |   4 +
 tests/fn_deep_equal/gold/test2.out                 |   4 +
 tests/fn_deep_equal/gold/test3.out                 |   4 +
 tests/fn_deep_equal/gold/test4.out                 |   4 +
 tests/fn_deep_equal/test1.xsl                      |  42 ++++
 tests/fn_deep_equal/test1_a.xml                    |  17 ++
 tests/fn_deep_equal/test1_b.xml                    |  17 ++
 tests/fn_deep_equal/test2.xsl                      |  44 +++++
 tests/fn_deep_equal/test2_a.xml                    |  18 ++
 tests/fn_deep_equal/test3.xsl                      |  48 +++++
 .../org/apache/xalan/xpath3/FnDeepEqualTests.java  |  92 +++++++++
 tests/org/apache/xalan/xslt3/Xsl3TestSuite1.java   |   4 +-
 16 files changed, 643 insertions(+), 6 deletions(-)

diff --git a/src/org/apache/xpath/compiler/FunctionTable.java b/src/org/apache/xpath/compiler/FunctionTable.java
index af53ca94..ac04a061 100644
--- a/src/org/apache/xpath/compiler/FunctionTable.java
+++ b/src/org/apache/xpath/compiler/FunctionTable.java
@@ -329,6 +329,9 @@ public class FunctionTable
   
   /** The 'node-name()' id. */
   public static final int FUNC_NODE_NAME = 101;
+  
+  /** The 'deep-equal()' id. */
+  public static final int FUNC_DEEP_EQUAL = 102;
 
   // Proprietary
 
@@ -386,7 +389,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 = 102;
+  private static final int NUM_BUILT_IN_FUNCS = 103;
 
   /**
    * Number of built-in functions that may be added.
@@ -590,6 +593,7 @@ public class FunctionTable
     m_functions[FUNC_DOC] = org.apache.xpath.functions.FuncDoc.class;
     
     m_functions[FUNC_NODE_NAME] = org.apache.xpath.functions.FuncNodeName.class;
+    m_functions[FUNC_DEEP_EQUAL] = org.apache.xpath.functions.FuncDeepEqual.class;
   }
 
   static{
@@ -806,6 +810,8 @@ public class FunctionTable
          
          m_functionID.put(Keywords.FUNC_NODE_NAME,
                          new Integer(FunctionTable.FUNC_NODE_NAME));
+         m_functionID.put(Keywords.FUNC_DEEP_EQUAL,
+                         new Integer(FunctionTable.FUNC_DEEP_EQUAL));
   }
   
   public FunctionTable(){
diff --git a/src/org/apache/xpath/compiler/Keywords.java b/src/org/apache/xpath/compiler/Keywords.java
index 720013fc..5ba8fc3f 100644
--- a/src/org/apache/xpath/compiler/Keywords.java
+++ b/src/org/apache/xpath/compiler/Keywords.java
@@ -463,6 +463,9 @@ public class Keywords
   /** node-name function string. */
   public static final String FUNC_NODE_NAME = "node-name";
   
+  /** deep-equal function string. */
+  public static final String FUNC_DEEP_EQUAL = "deep-equal";
+  
   // Proprietary, built in functions
 
   /** current function string (Proprietary). */
diff --git a/src/org/apache/xpath/functions/FuncDeepEqual.java b/src/org/apache/xpath/functions/FuncDeepEqual.java
new file mode 100644
index 00000000..ee12d20a
--- /dev/null
+++ b/src/org/apache/xpath/functions/FuncDeepEqual.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+package org.apache.xpath.functions;
+
+import javax.xml.transform.SourceLocator;
+
+import org.apache.xalan.xslt.util.XslTransformEvaluationHelper;
+import org.apache.xpath.Expression;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.ResultSequence;
+import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XObject;
+
+import xml.xpath31.processor.types.XSBoolean;
+
+/**
+ * Execute the deep-equal() function.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FuncDeepEqual extends FunctionMultiArgs {
+
+  private static final long serialVersionUID = -7233896041672168880L;
+
+  /**
+   * 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 = new XSBoolean(true);
+	  
+	  SourceLocator srcLocator = xctxt.getSAXLocator();
+	  
+	  Expression arg0 = getArg0();
+	  Expression arg1 = getArg1();
+	  
+	  if ((arg0 == null) || (arg1 == null)) {
+		 throw new javax.xml.transform.TransformerException("FOAP0001 : The number of arguments specified while "
+		 		                                                   + "calling deep-equal() function is wrong. Expected "
+		 		                                                   + "number of arguments for deep-equal() function is two "
+		 		                                                   + "or three.", srcLocator);  
+	  }
+	  
+	  XObject arg0Val = arg0.execute(xctxt);
+	  XObject arg1Val = arg1.execute(xctxt);
+	  
+      Expression arg2 = getArg2();  // an optional collation argument. REVISIT
+	  
+	  XObject collationVal = null;
+	  
+	  if (arg2 != null) {
+		 collationVal = arg2.execute(xctxt);   
+	  }
+	  
+	  ResultSequence resultSeq0 = XslTransformEvaluationHelper.getResultSequenceFromXObject(arg0Val, xctxt);
+	  
+	  ResultSequence resultSeq1 = XslTransformEvaluationHelper.getResultSequenceFromXObject(arg1Val, xctxt);
+	  
+	  boolean isNodesUnequal = false;
+	  
+	  if (resultSeq0.size() == resultSeq1.size()) {		 
+		 for (int idx1 = 0; idx1 < resultSeq0.size(); idx1++) {
+			for (int idx2 = 0; idx2 < resultSeq1.size(); idx2++) {
+			  if (idx1 == idx2) {
+				 XObject item1 = resultSeq0.item(idx1);
+				 XObject item2 = resultSeq1.item(idx2);
+				 if (item1.getType() != item2.getType()) {
+					result = new XSBoolean(false);
+					isNodesUnequal = true;
+					break;
+				 }
+			     else if ((item1.getType() == XObject.CLASS_NODESET) && 
+						  (item2.getType() == XObject.CLASS_NODESET)) {
+					XNodeSet node1 = (XNodeSet)item1;
+					XNodeSet node2 = (XNodeSet)item2;
+					if (!node1.equalsWithNodeName(node2, xctxt)) {
+					   result = new XSBoolean(false);
+					   isNodesUnequal = true;
+					   break;  
+					}
+				 }
+				 else if (!item1.vcEquals(item2, null, true)) {
+					result = new XSBoolean(false);
+					isNodesUnequal = true;
+					break;
+				 }										
+			  }			 			 
+		  }
+			 
+		  if (isNodesUnequal) {
+			 break; 
+		  }
+	   }
+	 }
+	 else {
+	    result = new XSBoolean(false);  
+	 }
+	
+	 return result;
+  }
+  
+}
diff --git a/src/org/apache/xpath/objects/XNodeSet.java b/src/org/apache/xpath/objects/XNodeSet.java
index 419e5b3c..8e5ef143 100644
--- a/src/org/apache/xpath/objects/XNodeSet.java
+++ b/src/org/apache/xpath/objects/XNodeSet.java
@@ -28,7 +28,9 @@ import org.apache.xml.dtm.DTMIterator;
 import org.apache.xml.dtm.DTMManager;
 import org.apache.xml.utils.XMLString;
 import org.apache.xpath.NodeSetDTM;
+import org.apache.xpath.XPathContext;
 import org.apache.xpath.axes.NodeSequence;
+import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.w3c.dom.traversal.NodeIterator;
 
@@ -37,17 +39,21 @@ import xml.xpath31.processor.types.XSUntyped;
 /**
  * This class represents an XPath nodeset object, and is capable of
  * converting the nodeset to other types, such as a string.
+ * 
+ * For XPath 3.1 processor, we use an object of this class along with 
+ * ResultSequence object and an XObject instance to be treated as 
+ * representations of sequence.
+ * 
  * @xsl.usage general
  */
 public class XNodeSet extends NodeSequence
 {  
-    static final long serialVersionUID = 1916026368035639667L;
+  static final long serialVersionUID = 1916026368035639667L;
+  
   /**
    * Default constructor for derived objects.
    */
-  protected XNodeSet()
-  {
-  }
+  protected XNodeSet() { }
 
   /**
    * Construct a XNodeSet object.
@@ -696,6 +702,148 @@ public class XNodeSet extends NodeSequence
 
     return result;
   }
+  
+  /*
+   * Check whether two xdm nodes are functionally equal, on the basis
+   * of string values of their names, and string values of nodes 
+   * themselves.
+   */
+  public boolean compareWithNodeNames(XObject obj2, XPathContext xctxt, 
+		                             Comparator comparator) throws javax.xml.transform.TransformerException {
+
+	    boolean result = false;
+	    
+	    int obj2Type = obj2.getType();
+	
+	    if (obj2Type == XObject.CLASS_NODESET) {
+		   DTMIterator dtmIter1 = iterRaw();
+		   DTMIterator dtmIter2 = ((XNodeSet) obj2).iterRaw();
+		   int nodeHandle1;
+		
+		   while ((nodeHandle1 = dtmIter1.nextNode()) != DTM.NULL) {
+		        XMLString s1 = getStringFromNode(nodeHandle1);
+		          
+		        int nodeHandle2;
+		
+		        while ((nodeHandle2 = dtmIter2.nextNode()) != DTM.NULL) {
+		            XMLString s2 = getStringFromNode(nodeHandle2);
+		
+		            if (comparator.compareStrings(s1, s2)) {
+		               DTM dtm1 = xctxt.getDTM(nodeHandle1);
+		     	       Node node1 = dtm1.getNode(nodeHandle1);
+		     	       DTM dtm2 = xctxt.getDTM(nodeHandle2);
+		     	       Node node2 = dtm2.getNode(nodeHandle2);
+		     	       if (isNodeNameEqual(node1, node2)) {
+		     	    	  result = true;  
+		     	       }		              
+		
+		               break;
+		            }
+		        }
+		  }
+		      
+		  dtmIter1.reset();
+		  dtmIter2.reset();
+	   }
+	   else if (obj2Type == XObject.CLASS_RESULT_SEQUENCE) {        
+	      ResultSequence rSeq = (ResultSequence)obj2;
+	        
+	      DTMIterator list1 = iterRaw();        
+	      int nodeHandle1;
+	      while ((nodeHandle1 = list1.nextNode()) != DTM.NULL) {
+	         XMLString s1 = getStringFromNode(nodeHandle1);
+	            
+	         for (int idx = 0; idx < rSeq.size(); idx++) {
+	            XObject xObj = rSeq.item(idx);               
+	            XMLString s2 = new XString(xObj.str());
+	            if (comparator.compareStrings(s1, s2))
+	            {
+	                DTM dtm = xctxt.getDTM(nodeHandle1);
+		     	    Node node1 = dtm.getNode(nodeHandle1);
+		     	    if (xObj instanceof XNodeSet) {
+		     	       XNodeSet xObjNodeSet = (XNodeSet)xObj;
+		     	       int nodeHandle2 = (xObjNodeSet.iter()).nextNode();
+		     	       DTM dtm2 = xctxt.getDTM(nodeHandle2);
+		     	       Node node2 = dtm.getNode(nodeHandle2);
+		     	       if (isNodeNameEqual(node1, node2)) {
+		     	    	  result = true;  
+		     	       }
+		     	    }
+		     	    else {
+		     	       result = true;   
+		     	    }
+		
+		            break;
+	            }
+	         }
+	            
+	         if (result) {
+	            break;  
+	         }
+	      }        
+	   }
+	   else if (obj2Type == XObject.CLASS_BOOLEAN) {
+	      double num1 = bool() ? 1.0 : 0.0;
+	      double num2 = obj2.num();
+	
+	      result = comparator.compareNumbers(num1, num2);
+	   }
+	   else if (obj2Type == XObject.CLASS_NUMBER) {     
+	      DTMIterator list1 = iterRaw();
+	      double num2 = obj2.num();
+	      int node;
+	
+	      while ((node = list1.nextNode()) != DTM.NULL) {
+	        double num1 = getNumberFromNode(node);
+	
+	        if (comparator.compareNumbers(num1, num2)) {
+	          result = true;	
+	          break;
+	        }
+	      }
+	      
+	      list1.reset();
+	   }
+	   else if (obj2Type == XObject.CLASS_STRING) {
+	      XMLString s2 = obj2.xstr();
+	      DTMIterator list1 = iterRaw();
+	      int node;
+	
+	      while ((node = list1.nextNode()) != DTM.NULL) {
+	        XMLString s1 = getStringFromNode(node);
+	        if (comparator.compareStrings(s1, s2)) {
+	          result = true;
+	
+	          break;
+	        }
+	      }
+	      
+	      list1.reset();
+	    }
+	    else if (obj2 instanceof XSUntyped) {
+	       XSUntyped obj2Val = (XSUntyped)obj2;
+	       
+	       XMLString s2 = new XString(obj2Val.stringValue());
+	       DTMIterator list1 = iterRaw();
+	       int node;
+	
+	       while ((node = list1.nextNode()) != DTM.NULL) {
+	         XMLString s1 = getStringFromNode(node);
+	         if (comparator.compareStrings(s1, s2)) {
+	           result = true;
+	
+	           break;
+	         }
+	       }
+	       
+	       list1.reset();       
+	    }
+	    else {
+	       result = comparator.compareNumbers(this.num(), obj2.num());
+	    }
+	
+	    return result;
+  }
 
   /**
    * Tell if one object is less than the other.
@@ -774,6 +922,22 @@ public class XNodeSet extends NodeSequence
       throw new org.apache.xml.utils.WrappedRuntimeException(te);
     }
   }
+  
+  /*
+   * Check whether two xdm nodes are equal, considering string
+   * values of their names as well.
+   */
+  public boolean equalsWithNodeName(XObject obj2, XPathContext xctxt)
+  {
+    try
+    {
+       return compareWithNodeNames(obj2, xctxt, S_EQ);
+    }
+    catch(javax.xml.transform.TransformerException te)
+    {
+       throw new org.apache.xml.utils.WrappedRuntimeException(te);
+    }
+  }
 
   /**
    * Tell if two objects are functionally not equal.
@@ -788,6 +952,50 @@ public class XNodeSet extends NodeSequence
   {
     return compare(obj2, S_NEQ);
   }
+  
+  /*
+   * Check whether fully qualified names of two XML nodes are equal.
+   */
+  private boolean isNodeNameEqual(Node node1, Node node2) {	 
+	 boolean isNodeNameEqual = false;
+	 
+	 if ((node1.getNodeType() == Node.ELEMENT_NODE) && (node2.getNodeType() == Node.ELEMENT_NODE)) {
+		String localName1 = node1.getLocalName();
+		String localName2 = node2.getLocalName();
+		if (localName1.equals(localName2) && isNsNameEqual(node1.getNamespaceURI(), node2.getNamespaceURI())) {
+		   isNodeNameEqual = true;
+		}
+	 }
+	 if ((node1.getNodeType() == Node.ATTRIBUTE_NODE) && (node2.getNodeType() == Node.ATTRIBUTE_NODE)) {
+		String localName1 = node1.getLocalName();
+		String localName2 = node2.getLocalName();
+		if (localName1.equals(localName2) && isNsNameEqual(node1.getNamespaceURI(), node2.getNamespaceURI())) {
+		   isNodeNameEqual = true;
+		}
+	 }
+	 else if ((node1.getNodeType() == Node.TEXT_NODE) && (node2.getNodeType() == Node.TEXT_NODE)) {
+		isNodeNameEqual = true;	 
+	 }
+	 
+	 return isNodeNameEqual;
+  }
+  
+  /*
+   * Check whether two XML namespace names are equal.
+   */
+  private boolean isNsNameEqual(String nsName1, String nsName2) {	 
+	 boolean isNsNameEqual = true;
+	 
+	 if (((nsName1 != null) && (nsName2 == null)) || 
+		  ((nsName1 == null) && (nsName2 != null))) {
+		isNsNameEqual = false; 
+	 }
+	 else if ((nsName1 != null) && (nsName2 != null) && nsName1.equals(nsName2)) {
+		isNsNameEqual = true; 
+	 }
+	 
+	 return isNsNameEqual;
+  }
 }
 
 /**
diff --git a/tests/fn_deep_equal/gold/test1.out b/tests/fn_deep_equal/gold/test1.out
new file mode 100644
index 00000000..05e5bb77
--- /dev/null
+++ b/tests/fn_deep_equal/gold/test1.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>true</one>
+  <two>false</two>
+</result>
diff --git a/tests/fn_deep_equal/gold/test2.out b/tests/fn_deep_equal/gold/test2.out
new file mode 100644
index 00000000..d6d7e43a
--- /dev/null
+++ b/tests/fn_deep_equal/gold/test2.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>false</one>
+  <two>false</two>
+</result>
diff --git a/tests/fn_deep_equal/gold/test3.out b/tests/fn_deep_equal/gold/test3.out
new file mode 100644
index 00000000..33530963
--- /dev/null
+++ b/tests/fn_deep_equal/gold/test3.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>false</one>
+  <two>true</two>
+</result>
diff --git a/tests/fn_deep_equal/gold/test4.out b/tests/fn_deep_equal/gold/test4.out
new file mode 100644
index 00000000..33530963
--- /dev/null
+++ b/tests/fn_deep_equal/gold/test4.out
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><result>
+  <one>false</one>
+  <two>true</two>
+</result>
diff --git a/tests/fn_deep_equal/test1.xsl b/tests/fn_deep_equal/test1.xsl
new file mode 100644
index 00000000..35b1af95
--- /dev/null
+++ b/tests/fn_deep_equal/test1.xsl
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+  <!-- Author: mukulg@apache.org -->
+  
+  <!-- An XSLT stylesheet test case, to test XPath 3.1 
+       function fn:deep-equal. 
+  -->                 
+  
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/root">
+     <result>
+       <one>
+         <xsl:value-of select="deep-equal(a/*, b/*)"/>
+       </one>
+       <two>
+         <xsl:value-of select="deep-equal(b/*, c/*)"/>
+       </two>
+     </result>
+  </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>
\ No newline at end of file
diff --git a/tests/fn_deep_equal/test1_a.xml b/tests/fn_deep_equal/test1_a.xml
new file mode 100644
index 00000000..77df561e
--- /dev/null
+++ b/tests/fn_deep_equal/test1_a.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <a>
+    <itm1/>
+    <itm2/>
+    <itm3/>
+  </a>
+  <b>
+    <itm1/>
+    <itm2/>
+    <itm3/>
+  </b>
+  <c>
+    <itm1/>
+    <itm2/>
+  </c>
+</root>
diff --git a/tests/fn_deep_equal/test1_b.xml b/tests/fn_deep_equal/test1_b.xml
new file mode 100644
index 00000000..3ac81aae
--- /dev/null
+++ b/tests/fn_deep_equal/test1_b.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <a>
+    <itm1>mn1</itm1>
+    <itm2/>
+    <itm3/>
+  </a>
+  <b>
+    <itm1>mn2</itm1>
+    <itm2/>
+    <itm3/>
+  </b>
+  <c>
+    <itm1/>
+    <itm2/>
+  </c>
+</root>
diff --git a/tests/fn_deep_equal/test2.xsl b/tests/fn_deep_equal/test2.xsl
new file mode 100644
index 00000000..3f445e82
--- /dev/null
+++ b/tests/fn_deep_equal/test2.xsl
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="3.0">
+                
+  <!-- Author: mukulg@apache.org -->
+  
+  <!-- use with test2_a.xml -->
+  
+  <!-- An XSLT stylesheet test case, to test XPath 3.1 
+       function fn:deep-equal. 
+  -->                
+  
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/root">
+     <result>
+       <one>
+         <xsl:value-of select="deep-equal(a//node() | a//@*, b//node() | b//@*)"/>
+       </one>
+       <two>
+         <xsl:value-of select="deep-equal(a//node() | a//@*, c//node() | c//@*)"/>
+       </two>
+     </result>
+  </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>
\ No newline at end of file
diff --git a/tests/fn_deep_equal/test2_a.xml b/tests/fn_deep_equal/test2_a.xml
new file mode 100644
index 00000000..40c32b09
--- /dev/null
+++ b/tests/fn_deep_equal/test2_a.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <a>
+    <itm1/>
+    <itm2 attr1="a"/>
+    <itm3/>
+  </a>
+  <b>
+    <itm1/>
+    <itm2 attr1="b"/>
+    <itm3/>
+  </b>
+  <c>
+    <itm1/>
+    <itm2 attr1="a"/>
+    <itm3/>
+  </c>
+</root>
diff --git a/tests/fn_deep_equal/test3.xsl b/tests/fn_deep_equal/test3.xsl
new file mode 100644
index 00000000..9959b05b
--- /dev/null
+++ b/tests/fn_deep_equal/test3.xsl
@@ -0,0 +1,48 @@
+<?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 XSLT stylesheet test case, to test XPath 3.1 
+       function fn:deep-equal. 
+  -->                
+  
+  <xsl:output method="xml" indent="yes"/>
+  
+  <xsl:template match="/">
+     <result>
+       <one>
+         <xsl:variable name="seq1" select="(xs:integer(1), xs:integer(2))"/>
+         <xsl:variable name="seq2" select="(xs:integer(1), xs:string('hello1'))"/>
+         <xsl:value-of select="deep-equal($seq1, $seq2)"/>
+       </one>
+       <two>
+         <xsl:variable name="seq3" select="(xs:integer(1), xs:integer(2))"/>
+	     <xsl:variable name="seq4" select="(xs:integer(1), xs:integer(2))"/>
+         <xsl:value-of select="deep-equal($seq3, $seq4)"/>
+       </two>
+     </result>
+  </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>
\ No newline at end of file
diff --git a/tests/org/apache/xalan/xpath3/FnDeepEqualTests.java b/tests/org/apache/xalan/xpath3/FnDeepEqualTests.java
new file mode 100644
index 00000000..46672b13
--- /dev/null
+++ b/tests/org/apache/xalan/xpath3/FnDeepEqualTests.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+package org.apache.xalan.xpath3;
+
+import org.apache.xalan.util.XslTransformTestsUtil;
+import org.apache.xalan.xslt3.XSLConstants;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * XPath 3.1 function fn:deep-equal test cases.
+ * 
+ * @author Mukul Gandhi <mu...@apache.org>
+ * 
+ * @xsl.usage advanced
+ */
+public class FnDeepEqualTests extends XslTransformTestsUtil {        
+    
+    private static final String XSL_TRANSFORM_INPUT_DIRPATH = XSLConstants.XSL_TRANSFORM_INPUT_DIRPATH_PREFIX + 
+    		                                                                                               "fn_deep_equal/";
+    
+    private static final String XSL_TRANSFORM_GOLD_DIRPATH = XSLConstants.XSL_TRANSFORM_GOLD_DIRPATH_PREFIX + 
+    		                                                                                               "fn_deep_equal/gold/";
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+       // no op
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {        
+        xmlDocumentBuilderFactory = null;
+        xmlDocumentBuilder = null;
+        xslTransformerFactory = null;
+    }
+
+    @Test
+    public void xslFnDeepEqualTest1() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_a.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test1.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnDeepEqualTest2() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1_b.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test1.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test2.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnDeepEqualTest3() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test2_a.xml"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test2.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test3.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+    
+    @Test
+    public void xslFnDeepEqualTest4() {
+        String xmlFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl"; 
+        String xslFilePath = XSL_TRANSFORM_INPUT_DIRPATH + "test3.xsl";
+        
+        String goldFilePath = XSL_TRANSFORM_GOLD_DIRPATH + "test4.out";                
+        
+        runXslTransformAndAssertOutput(xmlFilePath, xslFilePath, goldFilePath, null);
+    }
+
+}
diff --git a/tests/org/apache/xalan/xslt3/Xsl3TestSuite1.java b/tests/org/apache/xalan/xslt3/Xsl3TestSuite1.java
index 57ac2338..1962ed31 100644
--- a/tests/org/apache/xalan/xslt3/Xsl3TestSuite1.java
+++ b/tests/org/apache/xalan/xslt3/Xsl3TestSuite1.java
@@ -18,6 +18,7 @@ package org.apache.xalan.xslt3;
 
 import org.apache.xalan.xpath3.FnAbsTests;
 import org.apache.xalan.xpath3.FnDataTests;
+import org.apache.xalan.xpath3.FnDeepEqualTests;
 import org.apache.xalan.xpath3.FnDocTests;
 import org.apache.xalan.xpath3.FnForEachTests;
 import org.apache.xalan.xpath3.InlineFunctionItemExprTests;
@@ -45,7 +46,8 @@ import org.junit.runners.Suite.SuiteClasses;
                 ValueComparisonTests.class, InlineFunctionItemExprTests.class, 
                 FnForEachTests.class, XsConstructorFunctionTests.class,
                 FnAbsTests.class, StringTests.class, XsDateTimeArithmeticTests.class,
-                XsTimeWithArithmeticTests.class, XsDurationSubtypes.class })
+                XsTimeWithArithmeticTests.class, XsDurationSubtypes.class,
+                FnDeepEqualTests.class })
 public class Xsl3TestSuite1 {
 
 }


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