When I have a collection of nodes (here named mat), each having several children, the assertXmlEqual fails when the sequence of the toplevel nodes (mat) are different in the control and test xml, even though the content of the two mat-nodes are equal.
Is this a bug or unsupported feature, or must the elements in a collection have the same sequence for the collection to be considered equal?
String control = "<eiendomer><mat><nr>1</nr></mat><mat><nr>4</nr></mat></eiendomer>";
String test = "<eiendomer><mat><nr>4</nr></mat><mat><nr>1</nr></mat></eiendomer>";
xmlTestCase.assertXMLEqual(control, test);
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes: XMLUnit will flag child elements with repeated names as different if they are presented in a different sequence. (This is because it requires different qualified xpaths to reach the inner 'nr' nodes which are comparable: /eiendomer[1]/mat[1]/nr[1] vs. /eiendomer[1]/mat[2]/nr[1]).
However this is not the first request to be able to have finer grained control over the strategy for determining which nodes should be compared when a difference is evaluated.
So I have updated the source in CVS (at http://sourceforge.net/cvs/?group_id=23187\) to add an ElementQualifier interface that can be implemented as you see fit, and then supplied to the overrideElementQualifier() method of the Diff class.
This change will likely find its way into the 1.0 release of the project... let me know if you find it useful ;-)
Rgds,
Tim
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
>So I have updated the source in CVS (at http://sourceforge.net/cvs/?group_id=23187\) to add an ElementQualifier interface that can be implemented as you see fit, and then supplied to the overrideElementQualifier() method of the Diff class.
>This change will likely find its way into the 1.0 release of the project... let me know if you find it useful ;-)
This doesn't work with version 1.0 nor with the latest CVS version. Does anyone solved this?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Has anyone found any solution to this problem yet? I have a similar problem and have not been able to solve this.
I have written my own ElementQualifier class but it does not seem to have any impact (and yes, I do override it in my Diff object). The code for the qualifier is at the bottom of this message.
And finally here's my ElementQualifier. It is based on the ElementNameAndTextQualifier:
public class ElementNoSequenceQualifier extends ElementNameQualifier
{
public boolean qualifyForComparison(Element control, Element test)
{
if (super.qualifyForComparison(control, test))
{
boolean s = similar(extractText(control), extractText(test));
if (!s)
{
// Try to find element elsewhere in the xml tree
// Control element not present in current test element
Node parent = test.getParentNode();
if (parent != null)
{
Node nextParent = parent.getNextSibling();
while (nextParent != null || !s)
{
String sieblingName = nextParent.getNodeName();
String controlName = parent.getNodeName();
// Check if tag is the same as the control tag
if (sieblingName.equals(controlName))
{
// Check if tag has children
NodeList children = nextParent.getChildNodes();
for (int i = 0, size = children.getLength(); i < size && !s; i++)
{
Node c = children.item(i);
// Find control tag among children tags
if (c.getNodeName().equals(control.getNodeName()))
{
// Compare text
NodeList textNodes = c.getChildNodes();
for (int j = 0, count = textNodes.getLength(); j < count && !s; j++)
{
Node t = textNodes.item(j);
Text text = null;
if (t.getNodeType() == Node.TEXT_NODE)
text = (Text) t;
s = similar(extractText(control), text);
}
}
}
}
nextParent = nextParent.getNextSibling();
}
}
}
return s;
}
return false;
}
protected boolean similar(Text control, Text test)
{
if (control == null)
return test == null;
if (test == null)
return false;
else
return control.getNodeValue().equals(test.getNodeValue());
}
protected Text extractText(Element fromElement)
{
fromElement.normalize();
NodeList fromNodeList = fromElement.getChildNodes();
for (int i = 0; i < fromNodeList.getLength(); i++)
{
Node currentNode = fromNodeList.item(i);
if (currentNode.getNodeType() == Node.TEXT_NODE)
return (Text) currentNode;
}
return null;
}
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I don't think Tim said he solved the problem. He said he provided a way for others to solve the problem. However, this seems VERY useful, for a general population standpoint. Tim, is there any chance an implementation of ElementQualifier, that does solve the problem, will makes its way into CVS???
Thanks,
Jamie
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When I have a collection of nodes (here named mat), each having several children, the assertXmlEqual fails when the sequence of the toplevel nodes (mat) are different in the control and test xml, even though the content of the two mat-nodes are equal.
Is this a bug or unsupported feature, or must the elements in a collection have the same sequence for the collection to be considered equal?
String control = "<eiendomer><mat><nr>1</nr></mat><mat><nr>4</nr></mat></eiendomer>";
String test = "<eiendomer><mat><nr>4</nr></mat><mat><nr>1</nr></mat></eiendomer>";
xmlTestCase.assertXMLEqual(control, test);
Yes: XMLUnit will flag child elements with repeated names as different if they are presented in a different sequence. (This is because it requires different qualified xpaths to reach the inner 'nr' nodes which are comparable: /eiendomer[1]/mat[1]/nr[1] vs. /eiendomer[1]/mat[2]/nr[1]).
However this is not the first request to be able to have finer grained control over the strategy for determining which nodes should be compared when a difference is evaluated.
So I have updated the source in CVS (at http://sourceforge.net/cvs/?group_id=23187\) to add an ElementQualifier interface that can be implemented as you see fit, and then supplied to the overrideElementQualifier() method of the Diff class.
This change will likely find its way into the 1.0 release of the project... let me know if you find it useful ;-)
Rgds,
Tim
>So I have updated the source in CVS (at http://sourceforge.net/cvs/?group_id=23187\) to add an ElementQualifier interface that can be implemented as you see fit, and then supplied to the overrideElementQualifier() method of the Diff class.
>This change will likely find its way into the 1.0 release of the project... let me know if you find it useful ;-)
This doesn't work with version 1.0 nor with the latest CVS version. Does anyone solved this?
Has anyone found any solution to this problem yet? I have a similar problem and have not been able to solve this.
I have written my own ElementQualifier class but it does not seem to have any impact (and yes, I do override it in my Diff object). The code for the qualifier is at the bottom of this message.
The XML I am trying to compare looks like this:
<t1>
<t2>
<t3>one</t3>
</t2>
<t2>
<t3>two</t3>
</t2>
</t1>
and
<t1>
<t2>
<t3>two</t3>
</t2>
<t2>
<t3>one</t3>
</t2>
</t1>
and the code like this:
String xml1 = "<t1><t2><t3>one</t3></t2><t2><t3>two</t3></t2></t1>";
String xml2 = "<t1><t2><t3>two</t3></t2><t2><t3>one</t3></t2></t1>";
Diff diff = new Diff(xml1,xml2);
diff.overrideElementQualifier(new ElementNoSequenceQualifier());
assertXMLEqual(diff, true);
And finally here's my ElementQualifier. It is based on the ElementNameAndTextQualifier:
public class ElementNoSequenceQualifier extends ElementNameQualifier
{
public boolean qualifyForComparison(Element control, Element test)
{
if (super.qualifyForComparison(control, test))
{
boolean s = similar(extractText(control), extractText(test));
if (!s)
{
// Try to find element elsewhere in the xml tree
// Control element not present in current test element
Node parent = test.getParentNode();
if (parent != null)
{
Node nextParent = parent.getNextSibling();
while (nextParent != null || !s)
{
String sieblingName = nextParent.getNodeName();
String controlName = parent.getNodeName();
// Check if tag is the same as the control tag
if (sieblingName.equals(controlName))
{
// Check if tag has children
NodeList children = nextParent.getChildNodes();
for (int i = 0, size = children.getLength(); i < size && !s; i++)
{
Node c = children.item(i);
// Find control tag among children tags
if (c.getNodeName().equals(control.getNodeName()))
{
// Compare text
NodeList textNodes = c.getChildNodes();
for (int j = 0, count = textNodes.getLength(); j < count && !s; j++)
{
Node t = textNodes.item(j);
Text text = null;
if (t.getNodeType() == Node.TEXT_NODE)
text = (Text) t;
s = similar(extractText(control), text);
}
}
}
}
nextParent = nextParent.getNextSibling();
}
}
}
return s;
}
return false;
}
protected boolean similar(Text control, Text test)
{
if (control == null)
return test == null;
if (test == null)
return false;
else
return control.getNodeValue().equals(test.getNodeValue());
}
protected Text extractText(Element fromElement)
{
fromElement.normalize();
NodeList fromNodeList = fromElement.getChildNodes();
for (int i = 0; i < fromNodeList.getLength(); i++)
{
Node currentNode = fromNodeList.item(i);
if (currentNode.getNodeType() == Node.TEXT_NODE)
return (Text) currentNode;
}
return null;
}
}
I don't think Tim said he solved the problem. He said he provided a way for others to solve the problem. However, this seems VERY useful, for a general population standpoint. Tim, is there any chance an implementation of ElementQualifier, that does solve the problem, will makes its way into CVS???
Thanks,
Jamie