Visitar URL original
Introduce additional option to ignore child element's check. by hiufung-kwok · Pull Request #278 · xmlunit/xmlunit · GitHub
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ private XPathContext xpathContextFor(Node n) {
*/
ComparisonState compareNodes(final Node control, final XPathContext controlContext,
final Node test, final XPathContext testContext) {
System.out.println("Checking: " + test.toString());
final Iterable<Node> allControlChildren =
new IterableNodeList(control.getChildNodes());
final Iterable<Node> controlChildren =
Expand All @@ -149,6 +150,8 @@ ComparisonState compareNodes(final Node control, final XPathContext controlConte
final Iterable<Node> testChildren =
Linqy.filter(allTestChildren, getNodeFilter());

final boolean shouldIgnoreChild = shouldIgnoreChild(control);

return compare(new Comparison(ComparisonType.NODE_TYPE,
control, getXPath(controlContext),
control.getNodeType(), getParentXPath(controlContext),
Expand All @@ -164,7 +167,8 @@ control, getXPath(controlContext),
control.getPrefix(), getParentXPath(controlContext),
test, getXPath(testContext),
test.getPrefix(), getParentXPath(testContext)))
.andIfTrueThen(control.getNodeType() != Node.ATTRIBUTE_NODE,
.andIfTrueThen(control.getNodeType() != Node.ATTRIBUTE_NODE &&
!shouldIgnoreChild,
new Comparison(ComparisonType.CHILD_NODELIST_LENGTH,
control, getXPath(controlContext),
Linqy.count(controlChildren), getParentXPath(controlContext),
Expand All @@ -178,7 +182,8 @@ public ComparisonState apply() {
}
})
// and finally recurse into children
.andIfTrueThen(control.getNodeType() != Node.ATTRIBUTE_NODE,
.andIfTrueThen((control.getNodeType() != Node.ATTRIBUTE_NODE &&
!shouldIgnoreChild),
compareChildren(controlContext,
allControlChildren,
controlChildren,
Expand Down Expand Up @@ -402,7 +407,7 @@ private ComparisonState compareElementAttributes(final Element control,

return compare(new Comparison(ComparisonType.ELEMENT_NUM_ATTRIBUTES,
control, getXPath(controlContext),
controlAttributes.remainingAttributes.size(), getParentXPath(controlContext),
controlAttributes.getDataAttributeSizes(), getParentXPath(controlContext),
test, getXPath(testContext),
testAttributes.remainingAttributes.size(), getParentXPath(testContext)))
.andThen(new DeferredComparison() {
Expand Down Expand Up @@ -457,39 +462,41 @@ private NormalAttributeComparer(Element control,
public ComparisonState apply() {
ComparisonState chain = new OngoingComparisonState();
for (final Attr controlAttr : controlAttributes.remainingAttributes) {
final QName controlAttrName = Nodes.getQName(controlAttr);
final Attr testAttr =
findMatchingAttr(testAttributes.remainingAttributes,
controlAttr);
final QName testAttrName = testAttr != null
? Nodes.getQName(testAttr) : null;

controlContext.navigateToAttribute(controlAttrName);
try {
chain = chain.andThen(
new Comparison(ComparisonType.ATTR_NAME_LOOKUP,
control, getXPath(controlContext),
controlAttrName, getParentXPath(controlContext),
test, getXPath(testContext),
testAttrName, getParentXPath(testContext)));

if (testAttr != null) {
testContext.navigateToAttribute(testAttrName);
try {
chain = chain.andThen(new DeferredComparison() {
if (!controlAttr.getName().equals("placeholders:ignore")) {
final QName controlAttrName = Nodes.getQName(controlAttr);
final Attr testAttr =
findMatchingAttr(testAttributes.remainingAttributes,
controlAttr);
final QName testAttrName = testAttr != null
? Nodes.getQName(testAttr) : null;

controlContext.navigateToAttribute(controlAttrName);
try {
chain = chain.andThen(
new Comparison(ComparisonType.ATTR_NAME_LOOKUP,
control, getXPath(controlContext),
controlAttrName, getParentXPath(controlContext),
test, getXPath(testContext),
testAttrName, getParentXPath(testContext)));

if (testAttr != null) {
testContext.navigateToAttribute(testAttrName);
try {
chain = chain.andThen(new DeferredComparison() {
@Override
public ComparisonState apply() {
return compareNodes(controlAttr, controlContext,
testAttr, testContext);
testAttr, testContext);
}
});
foundTestAttributes.add(testAttr);
} finally {
testContext.navigateToParent();
foundTestAttributes.add(testAttr);
} finally {
testContext.navigateToParent();
}
}
} finally {
controlContext.navigateToParent();
}
} finally {
controlContext.navigateToParent();
}
}
return chain.andThen(new ControlAttributePresentComparer(control,
Expand Down Expand Up @@ -861,6 +868,20 @@ private Attributes(Attr schemaLocation, Attr noNamespaceSchemaLocation,
this.type = type;
this.remainingAttributes = remainingAttributes;
}

/**
* Return the number of attribute by minus the internal tag.
* @return int of Attr without the internal one.
*/
public int getDataAttributeSizes() {
int count = 0;
for (Attr attr : remainingAttributes) {
if (!attr.getName().startsWith("placeholders:ignore")) {
count++;
}
}
return count;
}
}

/**
Expand Down Expand Up @@ -896,4 +917,23 @@ private static Map<Node, Integer> index(final Iterable<Node> nodes) {
}
return Collections.unmodifiableMap(indices);
}


/**
* To first parse the attributeMap and check whether ignore option exist.
* @return a boolean to indicate whether should the caller proceed to check the child element.
*/
private boolean shouldIgnoreChild (Node node) {
final String IGNORE_OPTION_CONSTANT = "placeholders:ignore";
final String OPTION_RECURSIVE = "recursive";
// Nested null check should be improved when migrating to Java 8+.
if (node.getAttributes() != null &&
node.getAttributes().getNamedItem(IGNORE_OPTION_CONSTANT) != null &&
node.getAttributes().getNamedItem(IGNORE_OPTION_CONSTANT).getNodeValue() != null
) {
System.out.println("Ingnoring entries!");
return OPTION_RECURSIVE.equals(node.getAttributes().getNamedItem(IGNORE_OPTION_CONSTANT).getNodeValue());
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
import org.xmlunit.diff.*;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import static org.hamcrest.CoreMatchers.containsString;
Expand Down Expand Up @@ -472,4 +476,92 @@ public void isDateTimePlaceholder_Element_IsDateTime_CustomFormat() {
assertFalse(diff.hasDifferences());
}

@Test
public void ignoreSingleElement() throws Exception {

String control = "<device>\n" +
"<deviceType>Mobile</deviceType>\n" +
"<IMEI>${xmlunit.ignore}</IMEI>\n" +
"<deviceName>${xmlunit.ignore}</deviceName>\n" +
"</device>\n";
String test = "<device>\n" +
"<deviceType>Mobile</deviceType>\n" +
"<IMEI>12345678912345</IMEI>\n" +
"<deviceName>My Samsung</deviceName>\n" +
"</device>";
Diff diff = DiffBuilder.compare(control).withTest(test)
.withDifferenceEvaluator(new PlaceholderDifferenceEvaluator()).build();

assertFalse(diff.hasDifferences());
}

@Test
public void ignoreWholeElementRegardlessContent() throws Exception {

String control = "<device>" +
"<deviceType>Mobile</deviceType>" +
"<deviceDetails xmlns:placeholders=\"https://www.xmlunit.org/placeholders\" placeholders:ignore=\"recursive\"></deviceDetails>" +
"</device>";
String test = "<device>" +
"<deviceType>Mobile</deviceType>" +
"<deviceDetails>" +
" <IMEI>12345678912345</IMEI>" +
" <deviceName>My Samsung</deviceName>" +
" <deviceSerialNumber>XYZ-123</deviceSerialNumber>" +
"</deviceDetails>" +
"</device>";
Diff diff = DiffBuilder.compare(control).withTest(test)
.withDifferenceEvaluator(new PlaceholderDifferenceEvaluator()).build();

for (Difference item : diff.getDifferences()) {
System.out.println(item);
}

assertFalse(diff.hasDifferences());
}
//
// @Test
// public void test() throws Exception {
//
// String control = "<MetaData xmlns=\"urn:wco:datamodel:WCO:DocumentMetaData-DMS:2\">\n" +
// " <Declaration xmlns=\"urn:wco:datamodel:WCO:DEC-DMS:2\">\n" +
// " <FunctionCode>9</FunctionCode>\n" +
// " <deviceDetails xmlns:placeholders=\"https://www.xmlunit.org/placeholders\" placeholders:ignore=\"recursive\"/>\n" +
// " <FunctionalReferenceID>432189615698-46239</FunctionalReferenceID>\n" +
//// " <TypeCode>EXD</TypeCode>\n" +
// " <GoodsItemQuantity>11</GoodsItemQuantity>\n" +
// " <InvoiceAmount currencyID=\"GBP\">7001.00</InvoiceAmount>\n" +
// " </Declaration>\n" +
// "</MetaData>";
// String test = "<MetaData xmlns=\"urn:wco:datamodel:WCO:DocumentMetaData-DMS:2\">\n" +
// " <Declaration xmlns=\"urn:wco:datamodel:WCO:DEC-DMS:2\">\n" +
// " <FunctionCode>9</FunctionCode>\n" +
// " <AdditionalInformation>\n" +
// " <StatementCode>AG001</StatementCode>\n" +
// " <StatementDescription>AG001</StatementDescription>\n" +
// " <Pointer>\n" +
// " <SequenceNumeric>1</SequenceNumeric>\n" +
// " <DocumentSectionCode>42A</DocumentSectionCode>\n" +
// " </Pointer>\n" +
// " </AdditionalInformation>\n" +
// " <FunctionalReferenceID>432189615698-46239</FunctionalReferenceID>\n" +
// " <GoodsItemQuantity>11</GoodsItemQuantity>\n" +
// " <InvoiceAmount currencyID=\"GBP\">7001.00</InvoiceAmount>\n" +
// " </Declaration>\n" +
// "</MetaData>";
// Diff diff = DiffBuilder.compare(control).withTest(test)
// .withDifferenceEvaluator(new PlaceholderDifferenceEvaluator())
//// .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
// .ignoreWhitespace()
// .build();
//
// for (Difference item : diff.getDifferences()) {
// System.out.println(item);
// }
//
// assertFalse(diff.hasDifferences());
// }



}