From: <bo...@us...> - 2010-08-27 15:42:09
|
Revision: 438 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=438&view=rev Author: bodewig Date: 2010-08-27 15:42:01 +0000 (Fri, 27 Aug 2010) Log Message: ----------- track XPath information in DifferenceEngine Modified Paths: -------------- trunk/xmlunit/build.xml trunk/xmlunit/src/buildtools/codegen.xslt trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/AbstractDifferenceEngine.java trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Linqy.java trunk/xmlunit/src/main/net-core/diff/AbstractDifferenceEngine.cs trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml trunk/xmlunit/src/main/net-core/util/Linqy.cs trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs trunk/xmlunit/xmlunit.nant.build Modified: trunk/xmlunit/build.xml =================================================================== --- trunk/xmlunit/build.xml 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/build.xml 2010-08-27 15:42:01 UTC (rev 438) @@ -95,6 +95,7 @@ <param name="implements" expression="implements"/> <param name="summaryStart" expression="/** "/> <param name="summaryEnd" expression="*/"/> + <param name="getXPath" expression="getXPath"/> <param name="compareMethod" expression="compare"/> </xslt> Modified: trunk/xmlunit/src/buildtools/codegen.xslt =================================================================== --- trunk/xmlunit/src/buildtools/codegen.xslt 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/buildtools/codegen.xslt 2010-08-27 15:42:01 UTC (rev 438) @@ -27,6 +27,7 @@ <xsl:param name="implements"/> <xsl:param name="summaryStart"/> <xsl:param name="summaryEnd"/> + <xsl:param name="getXPath"/> <xsl:template match="class"> /* @@ -95,9 +96,9 @@ <xsl:template match="compare"> lastResult = <xsl:value-of select="$compareMethod"/>(new Comparison(ComparisonType.<xsl:value-of select="@type"/>, - control, null, + control, <xsl:value-of select="$getXPath"/>(controlContext), control.<xsl:value-of select="@property"/>, - test, null, + test, <xsl:value-of select="$getXPath"/>(testContext), test.<xsl:value-of select="@property"/>)); <xsl:call-template name="if-return-boilerplate"/> </xsl:template> @@ -105,20 +106,22 @@ <xsl:template match="compareExpr"> lastResult = <xsl:value-of select="$compareMethod"/>(new Comparison(ComparisonType.<xsl:value-of select="@type"/>, - control, null, + control, <xsl:value-of select="$getXPath"/>(controlContext), <xsl:value-of select="@controlExpr"/>, - test, null, + test, <xsl:value-of select="$getXPath"/>(testContext), <xsl:value-of select="@testExpr"/>)); <xsl:call-template name="if-return-boilerplate"/> </xsl:template> <xsl:template match="compareMethod"> - lastResult = <xsl:value-of select="@method"/>(control, test); + lastResult = <xsl:value-of select="@method"/>(control, controlContext, + test, testContext); <xsl:call-template name="if-return-boilerplate"/> </xsl:template> <xsl:template match="compareMethodExpr"> - lastResult = <xsl:value-of select="@method"/>(<xsl:value-of select="@controlExpr"/>, <xsl:value-of select="@testExpr"/>); + lastResult = <xsl:value-of select="@method"/>(<xsl:value-of select="@controlExpr"/>, controlContext, + <xsl:value-of select="@testExpr"/>, testContext); <xsl:call-template name="if-return-boilerplate"/> </xsl:template> Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/AbstractDifferenceEngine.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/AbstractDifferenceEngine.java 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/AbstractDifferenceEngine.java 2010-08-27 15:42:01 UTC (rev 438) @@ -93,4 +93,8 @@ listeners.fireComparisonPerformed(comp, altered); return altered; } + + protected static String getXPath(XPathContext ctx) { + return ctx == null ? null : ctx.getXPath(); + } } Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml 2010-08-27 15:42:01 UTC (rev 438) @@ -23,9 +23,12 @@ <import reference="java.util.Set"/> <import reference="java.util.TreeSet"/> <import reference="javax.xml.XMLConstants"/> + <import reference="javax.xml.namespace.QName"/> <import reference="javax.xml.transform.Source"/> <import reference="net.sf.xmlunit.util.Convert"/> <import reference="net.sf.xmlunit.util.IterableNodeList"/> + <import reference="net.sf.xmlunit.util.Linqy"/> + <import reference="net.sf.xmlunit.util.Nodes"/> <import reference="org.w3c.dom.Attr"/> <import reference="org.w3c.dom.CharacterData"/> <import reference="org.w3c.dom.Document"/> @@ -44,7 +47,8 @@ if (test == null) { throw new IllegalArgumentException("test must not be null"); } - compareNodes(Convert.toNode(control), Convert.toNode(test)); + compareNodes(Convert.toNode(control), new XPathContext(), + Convert.toNode(test), new XPathContext()); } /** @@ -59,7 +63,8 @@ * * <p>package private to support tests.</p> */ - ComparisonResult compareNodes(Node control, Node test) { + ComparisonResult compareNodes(Node control, XPathContext controlContext, + Node test, XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="NODE_TYPE" property="getNodeType()"/> @@ -74,7 +79,14 @@ testExpr="testChildren.getLength()"/> <compareMethod method="nodeTypeSpecificComparison"/> <literal><![CDATA[ - return compareNodeLists(controlChildren, testChildren); + controlContext + .setChildren(Linqy.map(new IterableNodeList(controlChildren), + TO_NODE_INFO)); + testContext + .setChildren(Linqy.map(new IterableNodeList(testChildren), + TO_NODE_INFO)); + return compareNodeLists(controlChildren, controlContext, + testChildren, testContext); } /** @@ -84,45 +96,50 @@ * <p>package private to support tests.</p> */ private ComparisonResult nodeTypeSpecificComparison(Node control, - Node test) { + XPathContext controlContext, + Node test, + XPathContext testContext) { switch (control.getNodeType()) { case Node.CDATA_SECTION_NODE: case Node.COMMENT_NODE: case Node.TEXT_NODE: if (test instanceof CharacterData) { return compareCharacterData((CharacterData) control, - (CharacterData) test); + controlContext, + (CharacterData) test, testContext); } break; case Node.DOCUMENT_NODE: if (test instanceof Document) { - return compareDocuments((Document) control, - (Document) test); + return compareDocuments((Document) control, controlContext, + (Document) test, testContext); } break; case Node.ELEMENT_NODE: if (test instanceof Element) { - return compareElements((Element) control, - (Element) test); + return compareElements((Element) control, controlContext, + (Element) test, testContext); } break; case Node.PROCESSING_INSTRUCTION_NODE: if (test instanceof ProcessingInstruction) { return compareProcessingInstructions((ProcessingInstruction) control, - (ProcessingInstruction) test); + controlContext, + (ProcessingInstruction) test, + testContext); } break; case Node.DOCUMENT_TYPE_NODE: if (test instanceof DocumentType) { - return compareDocTypes((DocumentType) control, - (DocumentType) test); + return compareDocTypes((DocumentType) control, controlContext, + (DocumentType) test, testContext); } break; case Node.ATTRIBUTE_NODE: if (test instanceof Attr) { - return compareAttributes((Attr) control, - (Attr) test); + return compareAttributes((Attr) control, controlContext, + (Attr) test, testContext); } break; } @@ -133,14 +150,20 @@ * Compares textual content. */ private ComparisonResult compareCharacterData(CharacterData control, - CharacterData test) { + XPathContext controlContext, + CharacterData test, + XPathContext testContext) { return compare(new Comparison(ComparisonType.TEXT_VALUE, control, - null, control.getData(), - test, null, test.getData())); + getXPath(controlContext), + control.getData(), + test, getXPath(testContext), + test.getData())); } private ComparisonResult compareDocuments(Document control, - Document test) { + XPathContext controlContext, + Document test, + XPathContext testContext) { DocumentType controlDt = control.getDoctype(); DocumentType testDt = test.getDoctype(); ]]></literal> @@ -161,12 +184,16 @@ <compare type="XML_STANDALONE" property="getXmlStandalone()"/> <literal><![CDATA[ return compare(new Comparison(ComparisonType.XML_ENCODING, - control, null, control.getXmlEncoding(), - test, null, test.getXmlEncoding())); + control, getXPath(controlContext), + control.getXmlEncoding(), + test, getXPath(testContext), + test.getXmlEncoding())); } private ComparisonResult compareDocTypes(DocumentType control, - DocumentType test) { + XPathContext controlContext, + DocumentType test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="DOCTYPE_NAME" property="getName()"/> @@ -178,13 +205,21 @@ } private ComparisonResult compareElements(Element control, - Element test) { + XPathContext controlContext, + Element test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="ELEMENT_TAG_NAME" property="getTagName()"/> <literal><![CDATA[ Attributes controlAttributes = splitAttributes(control.getAttributes()); + controlContext + .addAttributes(Linqy.map(controlAttributes.remainingAttributes, + QNAME_MAPPER)); Attributes testAttributes = splitAttributes(test.getAttributes()); + testContext + .addAttributes(Linqy.map(testAttributes.remainingAttributes, + QNAME_MAPPER)); Set<Attr> foundTestAttributes = new HashSet<Attr>(); ]]></literal> <compareExpr type="ELEMENT_NUM_ATTRIBUTES" @@ -196,27 +231,42 @@ findMatchingAttr(testAttributes.remainingAttributes, controlAttr); ]]></literal> + controlContext.navigateToAttribute(Nodes.getQName(controlAttr)); + try { <compareExpr type="ATTR_NAME_LOOKUP" controlExpr="Boolean.TRUE" testExpr="Boolean.valueOf(testAttr != null)"/> <literal><![CDATA[ - if (testAttr != null) { + if (testAttr != null) { + testContext.navigateToAttribute(Nodes.getQName(testAttr)); + try { ]]></literal> <compareMethodExpr method="compareNodes" controlExpr="controlAttr" testExpr="testAttr"/> <literal><![CDATA[ - foundTestAttributes.add(testAttr); + foundTestAttributes.add(testAttr); + } finally { + testContext.navigateToParent(); + } + } + } finally { + controlContext.navigateToParent(); } } ]]></literal> <literal><![CDATA[ for (Attr testAttr : testAttributes.remainingAttributes) { + testContext.navigateToAttribute(Nodes.getQName(testAttr)); + try { ]]></literal> <compareExpr type="ATTR_NAME_LOOKUP" controlExpr="Boolean.valueOf(foundTestAttributes.contains(testAttr))" testExpr="Boolean.TRUE"/> <literal><![CDATA[ + } finally { + testContext.navigateToParent(); + } } ]]></literal> <compareExpr type="SCHEMA_LOCATION" @@ -233,17 +283,24 @@ private ComparisonResult compareProcessingInstructions(ProcessingInstruction control, - ProcessingInstruction test) { + XPathContext controlContext, + ProcessingInstruction test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="PROCESSING_INSTRUCTION_TARGET" property="getTarget()"/> <literal><![CDATA[ return compare(new Comparison(ComparisonType.PROCESSING_INSTRUCTION_DATA, - control, null, control.getData(), - test, null, test.getData())); + control, getXPath(controlContext), + control.getData(), + test, getXPath(testContext), + test.getData())); } - private ComparisonResult compareNodeLists(NodeList control, NodeList test) { + private ComparisonResult compareNodeLists(NodeList control, + XPathContext controlContext, + NodeList test, + XPathContext testContext) { List<Node> controlList = IterableNodeList.asList(control); List<Node> testList = IterableNodeList.asList(test); final int testSize = testList.size(); @@ -259,48 +316,72 @@ final int controlSize = controlList.size(); Match lastMatch = new Match(null, -1); for (int i = 0; i < controlSize; i++) { - Match testMatch = findMatchingNode(controlList.get(i), testList, - lastMatch.index); - if (testMatch != null) { + controlContext.navigateToChild(i); + try { + Match testMatch = findMatchingNode(controlList.get(i), testList, + lastMatch.index); + if (testMatch != null) { ]]></literal> + testContext.navigateToChild(testMatch.index); + try { <compareMethodExpr method="compareNodes" controlExpr="controlList.get(i)" testExpr="testMatch.node"/> <literal><![CDATA[ - unmatchedTestIndexes.remove(Integer.valueOf(testMatch.index)); - lastMatch = testMatch; - } else { - lastResult = - compare(new Comparison(ComparisonType.CHILD_LOOKUP, - controlList.get(i), null, - controlList.get(i), - null, null, null)); + unmatchedTestIndexes + .remove(Integer.valueOf(testMatch.index)); + lastMatch = testMatch; + } finally { + testContext.navigateToParent(); + } + } else { + lastResult = + compare(new Comparison(ComparisonType.CHILD_LOOKUP, + controlList.get(i), + getXPath(controlContext), + controlList.get(i), + null, null, null)); ]]></literal> <if-return-boilerplate/> <literal><![CDATA[ + } + } finally { + controlContext.navigateToParent(); } } for (Integer I : unmatchedTestIndexes) { int i = I.intValue(); - lastResult = - compare(new Comparison(ComparisonType.CHILD_LOOKUP, - null, null, null, - testList.get(i), null, testList.get(i))); + testContext.navigateToChild(i); + try { + lastResult = + compare(new Comparison(ComparisonType.CHILD_LOOKUP, + null, null, null, + testList.get(i), + getXPath(testContext), + testList.get(i))); ]]></literal> <if-return-boilerplate/> <literal><![CDATA[ + } finally { + testContext.navigateToParent(); + } } return lastResult; } - private ComparisonResult compareAttributes(Attr control, Attr test) { + private ComparisonResult compareAttributes(Attr control, + XPathContext controlContext, + Attr test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="ATTR_VALUE_EXPLICITLY_SPECIFIED" property="getSpecified()"/> <literal><![CDATA[ return compare(new Comparison(ComparisonType.ATTR_VALUE, - control, null, control.getValue(), - test, null, test.getValue())); + control, getXPath(controlContext), + control.getValue(), + test, getXPath(testContext), + test.getValue())); } private static Attributes splitAttributes(final NamedNodeMap map) { @@ -395,5 +476,16 @@ } } + private static final Linqy.Mapper<Node, QName> QNAME_MAPPER = + new Linqy.Mapper<Node, QName>() { + public QName map(Node n) { return Nodes.getQName(n); } + }; + + private static final Linqy.Mapper<Node, XPathContext.NodeInfo> TO_NODE_INFO = + new Linqy.Mapper<Node, XPathContext.NodeInfo>() { + public XPathContext.NodeInfo map(Node n) { + return new XPathContext.DOMNodeInfo(n); + } + }; ]]></literal> </class> \ No newline at end of file Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Linqy.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Linqy.java 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Linqy.java 2010-08-27 15:42:01 UTC (rev 438) @@ -46,6 +46,19 @@ }; } + public static <F, T> Iterable<T> map(final Iterable<F> from, + final Mapper<? super F, T> mapper) { + return new Iterable<T>() { + public Iterator<T> iterator() { + return new MappingIterator<F, T>(from.iterator(), mapper); + } + }; + } + + public interface Mapper<F, T> { + T map(F from); + } + private static class CastingIterator<E> implements Iterator<E> { private final Iterator i; private CastingIterator(Iterator i) { @@ -82,4 +95,23 @@ return !iterated; } } + + private static class MappingIterator<F, T> implements Iterator<T> { + private final Iterator<F> i; + private final Mapper<? super F, T> mapper; + private MappingIterator(Iterator<F> i, Mapper<? super F, T> mapper) { + this.i = i; + this.mapper = mapper; + } + public void remove() { + i.remove(); + } + public T next() { + return mapper.map(i.next()); + } + public boolean hasNext() { + return i.hasNext(); + } + } + } \ No newline at end of file Modified: trunk/xmlunit/src/main/net-core/diff/AbstractDifferenceEngine.cs =================================================================== --- trunk/xmlunit/src/main/net-core/diff/AbstractDifferenceEngine.cs 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/main/net-core/diff/AbstractDifferenceEngine.cs 2010-08-27 15:42:01 UTC (rev 438) @@ -91,5 +91,9 @@ DifferenceListener(comp, outcome); } } + + protected static string GetXPath(XPathContext ctx) { + return ctx == null ? null : ctx.XPath; + } } } Modified: trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml =================================================================== --- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml 2010-08-27 15:42:01 UTC (rev 438) @@ -36,7 +36,9 @@ } CompareNodes(net.sf.xmlunit.util.Convert.ToNode(control), - net.sf.xmlunit.util.Convert.ToNode(test)); + new XPathContext(), + net.sf.xmlunit.util.Convert.ToNode(test), + new XPathContext()); } /// <summary> @@ -49,7 +51,10 @@ /// /// Stops as soon as any comparison returns ComparisonResult.CRITICAL. /// </remarks> - internal ComparisonResult CompareNodes(XmlNode control, XmlNode test) { + internal ComparisonResult CompareNodes(XmlNode control, + XPathContext controlContext, + XmlNode test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="NODE_TYPE" property="NodeType"/> @@ -64,7 +69,18 @@ testExpr="testChildren.Count"/> <compareMethod method="NodeTypeSpecificComparison"/> <literal><![CDATA[ - return CompareNodeLists(controlChildren, testChildren); + IEnumerable<XmlNode> cc = Linqy.Cast<XmlNode>(controlChildren); + controlContext + .SetChildren(Linqy.Map<XmlNode, + XPathContext.INodeInfo>(cc, + TO_NODE_INFO)); + IEnumerable<XmlNode> tc = Linqy.Cast<XmlNode>(testChildren); + testContext + .SetChildren(Linqy.Map<XmlNode, + XPathContext.INodeInfo>(tc, + TO_NODE_INFO)); + return CompareNodeLists(controlChildren, controlContext, + testChildren, testContext); } /// <summary> @@ -72,45 +88,56 @@ /// defined for the given combination of nodes. /// </summary> private ComparisonResult NodeTypeSpecificComparison(XmlNode control, - XmlNode test) { + XPathContext controlContext, + XmlNode test, + XPathContext testContext) { switch (control.NodeType) { case XmlNodeType.CDATA: case XmlNodeType.Comment: case XmlNodeType.Text: if (test is XmlCharacterData) { return CompareCharacterData((XmlCharacterData) control, - (XmlCharacterData) test); + controlContext, + (XmlCharacterData) test, + testContext); } break; case XmlNodeType.Document: if (test is XmlDocument) { return CompareDocuments((XmlDocument) control, - (XmlDocument) test); + controlContext, + (XmlDocument) test, testContext); } break; case XmlNodeType.Element: if (test is XmlElement) { return CompareElements((XmlElement) control, - (XmlElement) test); + controlContext, + (XmlElement) test, + testContext); } break; case XmlNodeType.ProcessingInstruction: if (test is XmlProcessingInstruction) { return CompareProcessingInstructions((XmlProcessingInstruction) control, - (XmlProcessingInstruction) test); + controlContext, + (XmlProcessingInstruction) test, + testContext); } break; case XmlNodeType.DocumentType: if (test is XmlDocumentType) { return CompareDocTypes((XmlDocumentType) control, - (XmlDocumentType) test); + controlContext, + (XmlDocumentType) test, testContext); } break; case XmlNodeType.Attribute: if (test is XmlAttribute) { return CompareAttributes((XmlAttribute) control, - (XmlAttribute) test); + controlContext, + (XmlAttribute) test, testContext); } break; } @@ -121,14 +148,20 @@ /// Compares textual content. /// </summary> private ComparisonResult CompareCharacterData(XmlCharacterData control, - XmlCharacterData test) { + XPathContext controlContext, + XmlCharacterData test, + XPathContext testContext) { return Compare(new Comparison(ComparisonType.TEXT_VALUE, control, - null, control.Data, - test, null, test.Data)); + GetXPath(controlContext), + control.Data, + test, GetXPath(testContext), + test.Data)); } private ComparisonResult CompareDocuments(XmlDocument control, - XmlDocument test) { + XPathContext controlContext, + XmlDocument test, + XPathContext testContext) { XmlDocumentType controlDt = control.DocumentType; XmlDocumentType testDt = test.DocumentType; ]]></literal> @@ -155,19 +188,25 @@ } private ComparisonResult CompareDocTypes(XmlDocumentType control, - XmlDocumentType test) { + XPathContext controlContext, + XmlDocumentType test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="DOCTYPE_NAME" property="Name"/> <compare type="DOCTYPE_PUBLIC_ID" property="PublicId"/> <literal><![CDATA[ return Compare(new Comparison(ComparisonType.DOCTYPE_SYSTEM_ID, - control, null, control.SystemId, - test, null, test.SystemId)); + control, GetXPath(controlContext), + control.SystemId, + test, GetXPath(testContext), + test.SystemId)); } private ComparisonResult CompareDeclarations(XmlDeclaration control, - XmlDeclaration test) { + XPathContext controlContext, + XmlDeclaration test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <literal><![CDATA[ @@ -193,18 +232,32 @@ control != null ? control.Encoding : string.Empty; string testEncoding = test != null ? test.Encoding : string.Empty; return Compare(new Comparison(ComparisonType.XML_ENCODING, - control, null, controlEncoding, - test, null, testEncoding)); + control, GetXPath(controlContext), + controlEncoding, + test, GetXPath(testContext), + testEncoding)); } private ComparisonResult CompareElements(XmlElement control, - XmlElement test) { + XPathContext controlContext, + XmlElement test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="ELEMENT_TAG_NAME" property="Name"/> <literal><![CDATA[ Attributes controlAttributes = SplitAttributes(control.Attributes); + controlContext + .AddAttributes(Linqy.Map<XmlAttribute, + XmlQualifiedName>(controlAttributes + .RemainingAttributes, + Nodes.GetQName)); Attributes testAttributes = SplitAttributes(test.Attributes); + testContext + .AddAttributes(Linqy.Map<XmlAttribute, + XmlQualifiedName>(testAttributes + .RemainingAttributes, + Nodes.GetQName)); IDictionary<XmlAttribute, object> foundTestAttributes = new Dictionary<XmlAttribute, object>(); ]]></literal> @@ -216,28 +269,44 @@ XmlAttribute testAttr = FindMatchingAttr(testAttributes.RemainingAttributes, controlAttr); + controlContext.NavigateToAttribute(Nodes.GetQName(controlAttr)); + try { ]]></literal> <compareExpr type="ATTR_NAME_LOOKUP" controlExpr="true" testExpr="testAttr != null"/> <literal><![CDATA[ - if (testAttr != null) { + if (testAttr != null) { + testContext.NavigateToAttribute(Nodes + .GetQName(testAttr)); + try { ]]></literal> <compareMethodExpr method="CompareNodes" controlExpr="controlAttr" testExpr="testAttr"/> <literal><![CDATA[ - foundTestAttributes[testAttr] = DUMMY; + foundTestAttributes[testAttr] = DUMMY; + } finally { + testContext.NavigateToParent(); + } + } + } finally { + controlContext.NavigateToParent(); } } ]]></literal> <literal><![CDATA[ foreach (XmlAttribute testAttr in testAttributes.RemainingAttributes) { + testContext.NavigateToAttribute(Nodes.GetQName(testAttr)); + try { ]]></literal> <compareExpr type="ATTR_NAME_LOOKUP" controlExpr="foundTestAttributes.ContainsKey(testAttr)" testExpr="true"/> <literal><![CDATA[ + } finally { + testContext.NavigateToParent(); + } } ]]></literal> <compareExpr type="SCHEMA_LOCATION" @@ -254,18 +323,24 @@ private ComparisonResult CompareProcessingInstructions(XmlProcessingInstruction control, - XmlProcessingInstruction test) { + XPathContext controlContext, + XmlProcessingInstruction test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="PROCESSING_INSTRUCTION_TARGET" property="Target"/> <literal><![CDATA[ return Compare(new Comparison(ComparisonType.PROCESSING_INSTRUCTION_DATA, - control, null, control.Data, - test, null, test.Data)); + control, GetXPath(controlContext), + control.Data, + test, GetXPath(testContext), + test.Data)); } private ComparisonResult CompareNodeLists(XmlNodeList control, - XmlNodeList test) { + XPathContext controlContext, + XmlNodeList test, + XPathContext testContext) { IList<XmlNode> controlList = new List<XmlNode>(Linqy.Cast<XmlNode>(control)); IList<XmlNode> testList = @@ -284,46 +359,67 @@ for (int i = 0; i < controlList.Count; i++) { Match testMatch = FindMatchingNode(controlList[i], testList, lastMatch.Index); - if (testMatch != null) { + controlContext.NavigateToChild(i); + try { + if (testMatch != null) { + testContext.NavigateToChild(testMatch.Index); + try { ]]></literal> <compareMethodExpr method="CompareNodes" controlExpr="controlList[i]" testExpr="testMatch.Node"/> <literal><![CDATA[ - unmatchedTestIndexes.Remove(testMatch.Index); - lastMatch = testMatch; - } else { - lastResult = - Compare(new Comparison(ComparisonType.CHILD_LOOKUP, - controlList[i], null, - controlList[i], - null, null, null)); + unmatchedTestIndexes.Remove(testMatch.Index); + lastMatch = testMatch; + } finally { + testContext.NavigateToParent(); + } + } else { + lastResult = + Compare(new Comparison(ComparisonType.CHILD_LOOKUP, + controlList[i], + GetXPath(controlContext), + controlList[i], + null, null, null)); ]]></literal> <if-return-boilerplate/> <literal><![CDATA[ + } + } finally { + controlContext.NavigateToParent(); } } foreach (int i in unmatchedTestIndexes.Keys) { - lastResult = - Compare(new Comparison(ComparisonType.CHILD_LOOKUP, - null, null, null, - testList[i], null, testList[i])); + testContext.NavigateToChild(i); + try { + lastResult = + Compare(new Comparison(ComparisonType.CHILD_LOOKUP, + null, null, null, + testList[i], GetXPath(testContext), + testList[i])); ]]></literal> <if-return-boilerplate/> <literal><![CDATA[ + } finally { + testContext.NavigateToParent(); + } } return lastResult; } private ComparisonResult CompareAttributes(XmlAttribute control, - XmlAttribute test) { + XPathContext controlContext, + XmlAttribute test, + XPathContext testContext) { ]]></literal> <lastResultDef/> <compare type="ATTR_VALUE_EXPLICITLY_SPECIFIED" property="Specified"/> <literal><![CDATA[ return Compare(new Comparison(ComparisonType.ATTR_VALUE, - control, null, control.Value, - test, null, test.Value)); + control, GetXPath(controlContext), + control.Value, + test, GetXPath(testContext), + test.Value)); } private static Attributes SplitAttributes(XmlAttributeCollection map) { @@ -414,5 +510,9 @@ Index = index; } } + + private static XPathContext.INodeInfo TO_NODE_INFO(XmlNode n) { + return new XPathContext.DOMNodeInfo(n); + } ]]></literal> </class> \ No newline at end of file Modified: trunk/xmlunit/src/main/net-core/util/Linqy.cs =================================================================== --- trunk/xmlunit/src/main/net-core/util/Linqy.cs 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/main/net-core/util/Linqy.cs 2010-08-27 15:42:01 UTC (rev 438) @@ -30,5 +30,13 @@ yield return t; } + public delegate T Mapper<F, T>(F from); + + public static IEnumerable<T> Map<F, T>(IEnumerable<F> from, + Mapper<F, T> mapper) { + foreach (F f in from) { + yield return mapper(f); + } + } } } \ No newline at end of file Modified: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java =================================================================== --- trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java 2010-08-27 10:54:58 UTC (rev 437) +++ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java 2010-08-27 15:42:01 UTC (rev 438) @@ -44,12 +44,27 @@ private int invoked = 0; private final int expectedInvocations; private final ComparisonType type; + private final boolean withXPath; + private final String controlXPath; + private final String testXPath; private DiffExpecter(ComparisonType type) { this(type, 1); } private DiffExpecter(ComparisonType type, int expected) { + this(type, expected, false, null, null); + } + private DiffExpecter(ComparisonType type, String controlXPath, + String testXPath) { + this(type, 1, true, controlXPath, testXPath); + } + private DiffExpecter(ComparisonType type, int expected, + boolean withXPath, String controlXPath, + String testXPath) { this.type = type; this.expectedInvocations = expected; + this.withXPath = withXPath; + this.controlXPath = controlXPath; + this.testXPath = testXPath; } public void comparisonPerformed(Comparison comparison, ComparisonResult outcome) { @@ -58,6 +73,12 @@ invoked++; assertEquals(type, comparison.getType()); assertEquals(ComparisonResult.CRITICAL, outcome); + if (withXPath) { + assertEquals("Control XPath", controlXPath, + comparison.getControlDetails().getXPath()); + assertEquals("Test XPath", testXPath, + comparison.getTestDetails().getXPath()); + } } } @@ -74,8 +95,8 @@ d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(doc.createElement("x"), - doc.createComment("x"))); + d.compareNodes(doc.createElement("x"), new XPathContext(), + doc.createComment("x"), new XPathContext())); assertEquals(1, ex.invoked); } @@ -85,8 +106,8 @@ d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(doc.createElement("x"), - doc.createElement("x"))); + d.compareNodes(doc.createElement("x"), new XPathContext(), + doc.createElement("x"), new XPathContext())); assertEquals(0, ex.invoked); } @@ -97,7 +118,9 @@ d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); assertEquals(ComparisonResult.CRITICAL, d.compareNodes(doc.createElementNS("x", "y"), - doc.createElementNS("z", "y"))); + new XPathContext(), + doc.createElementNS("z", "y"), + new XPathContext())); assertEquals(1, ex.invoked); } @@ -119,7 +142,9 @@ }); assertEquals(ComparisonResult.CRITICAL, d.compareNodes(doc.createElementNS("x", "x:y"), - doc.createElementNS("x", "z:y"))); + new XPathContext(), + doc.createElementNS("x", "z:y"), + new XPathContext())); assertEquals(1, ex.invoked); } @@ -131,14 +156,22 @@ d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); Element e1 = doc.createElement("x"); Element e2 = doc.createElement("x"); - assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); e1.appendChild(doc.createElement("x")); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); assertEquals(1, ex.invoked); e2.appendChild(doc.createElement("x")); - assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); e2.appendChild(doc.createElement("x")); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); assertEquals(2, ex.invoked); } @@ -174,42 +207,60 @@ CDATASection barCDATASection = doc.createCDATASection("bar"); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooComment, fooComment)); + d.compareNodes(fooComment, new XPathContext(), + fooComment, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooComment, barComment)); + d.compareNodes(fooComment, new XPathContext(), + barComment, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooText, fooText)); + d.compareNodes(fooText, new XPathContext(), + fooText, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooText, barText)); + d.compareNodes(fooText, new XPathContext(), + barText, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooCDATASection, fooCDATASection)); + d.compareNodes(fooCDATASection, new XPathContext(), + fooCDATASection, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooCDATASection, barCDATASection)); + d.compareNodes(fooCDATASection, new XPathContext(), + barCDATASection, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooComment, fooText)); + d.compareNodes(fooComment, new XPathContext(), + fooText, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooComment, barText)); + d.compareNodes(fooComment, new XPathContext(), + barText, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooComment, fooCDATASection)); + d.compareNodes(fooComment, new XPathContext(), + fooCDATASection, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooComment, barCDATASection)); + d.compareNodes(fooComment, new XPathContext(), + barCDATASection, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooText, fooComment)); + d.compareNodes(fooText, new XPathContext(), + fooComment, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooText, barComment)); + d.compareNodes(fooText, new XPathContext(), + barComment, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooText, fooCDATASection)); + d.compareNodes(fooText, new XPathContext(), + fooCDATASection, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooText, barCDATASection)); + d.compareNodes(fooText, new XPathContext(), + barCDATASection, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooCDATASection, fooText)); + d.compareNodes(fooCDATASection, new XPathContext(), + fooText, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooCDATASection, barText)); + d.compareNodes(fooCDATASection, new XPathContext(), + barText, new XPathContext())); assertEquals(ComparisonResult.EQUAL, - d.compareNodes(fooCDATASection, fooComment)); + d.compareNodes(fooCDATASection, new XPathContext(), + fooComment, new XPathContext())); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(fooCDATASection, barComment)); + d.compareNodes(fooCDATASection, new XPathContext(), + barComment, new XPathContext())); assertEquals(9, ex.invoked); } @@ -221,8 +272,12 @@ ProcessingInstruction foo1 = doc.createProcessingInstruction("foo", "1"); ProcessingInstruction bar1 = doc.createProcessingInstruction("bar", "1"); - assertEquals(ComparisonResult.EQUAL, d.compareNodes(foo1, foo1)); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(foo1, bar1)); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(foo1, new XPathContext(), + foo1, new XPathContext())); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(foo1, new XPathContext(), + bar1, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -230,8 +285,12 @@ d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); ProcessingInstruction foo2 = doc.createProcessingInstruction("foo", "2"); - assertEquals(ComparisonResult.EQUAL, d.compareNodes(foo1, foo1)); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(foo1, foo2)); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(foo1, new XPathContext(), + foo1, new XPathContext())); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(foo1, new XPathContext(), + foo2, new XPathContext())); assertEquals(1, ex.invoked); } @@ -266,7 +325,9 @@ + "\">" + "<Book/>") .build()); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(d1, d2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(d1, new XPathContext(), + d2, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -281,7 +342,8 @@ + " encoding=\"UTF-8\"?>" + "<Book/>").build()); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(d1, d2)); + d.compareNodes(d1, new XPathContext(), + d2, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -296,7 +358,8 @@ + " standalone=\"no\"?>" + "<Book/>").build()); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(d1, d2)); + d.compareNodes(d1, new XPathContext(), + d2, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -322,7 +385,8 @@ + " encoding=\"UTF-16\"?>" + "<Book/>").build()); assertEquals(ComparisonResult.CRITICAL, - d.compareNodes(d1, d2)); + d.compareNodes(d1, new XPathContext(), + d2, new XPathContext())); assertEquals(1, ex.invoked); } @@ -363,7 +427,9 @@ d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); DocumentType dt1 = new DocType("name", "pub", "system"); DocumentType dt2 = new DocType("name2", "pub", "system"); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(dt1, dt2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(dt1, new XPathContext(), + dt2, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -371,7 +437,9 @@ d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); dt2 = new DocType("name", "pub2", "system"); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(dt1, dt2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(dt1, new XPathContext(), + dt2, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -390,7 +458,9 @@ } }); dt2 = new DocType("name", "pub", "system2"); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(dt1, dt2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(dt1, new XPathContext(), + dt2, new XPathContext())); assertEquals(1, ex.invoked); } @@ -402,8 +472,12 @@ Element e1 = doc.createElement("foo"); Element e2 = doc.createElement("foo"); Element e3 = doc.createElement("bar"); - assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e3)); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(e1, new XPathContext(), + e3, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); @@ -411,15 +485,20 @@ e1.setAttribute("attr1", "value1"); d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); assertEquals(1, ex.invoked); d = new DOMDifferenceEngine(); - ex = new DiffExpecter(ComparisonType.ATTR_NAME_LOOKUP); + ex = new DiffExpecter(ComparisonType.ATTR_NAME_LOOKUP, + "/@attr1", "/"); e2.setAttributeNS("urn:xmlunit:test", "attr1", "value1"); d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); - assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); assertEquals(1, ex.invoked); @@ -438,7 +517,9 @@ e2.setAttributeNS(null, "attr1", "value1"); d.addDifferenceListener(ex); d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); - assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(e1, new XPathContext(), + e2, new XPathContext())); } @Test public void compareAttributes() { @@ -451,7 +532,9 @@ ... [truncated message content] |