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