Finding differences in two XML files using XMLUnit - java

How to check for only particular nodes and not all nodes for difference while using the DetailedDiff function of XMLUnit
this is my code:
public static void main(String[] args)
{
//URL url1 = xmlunittest.class.getResource("MSHIS1.xml");
// URL url2 = xmlunittest.class.getResource("MSHIS.xml");
Logger L = new Logger();
FileReader fr1 = null;
int countofdifferences = 0;
FileReader fr2 = null;
try {
fr1 = new FileReader("MSHIS.xml");
fr2 = new FileReader("MSHIS1.xml");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
Diff diff = new Diff(fr1, fr2);
L.writeToBVTLOG("Similar? " + diff.similar());
L.writeToBVTLOG("Identical? " + diff.identical());
DetailedDiff detDiff = new DetailedDiff(diff);
List differences = detDiff.getAllDifferences();
for (Object object : differences) {
Difference difference = (Difference)object;
L.writeToBVTLOG("------------------------");
L.writeToBVTLOG(difference.toString());
L.writeToBVTLOG("------------------------");
countofdifferences++;
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
L.writeToBVTLOG(countofdifferences);
}
But the thing is that, I just want the program to tell me if 4 particular nodes have undergone any changes. So how to get there from listing all the differences.

You can implement your own DifferenceListener that ignores some nodes (or only pays attention to some nodes) and tell XMLUnit to use it when checking differences. Here's a DifferenceListener that ignores any elements named "myelement":
public class IgnoreMyAttributeElements implements DifferenceListener()
{
#Override
public int differenceFound(Difference differenceIn)
{
Node controlNode = differenceIn.getControlNodeDetail().getNode();
if(controlNode.getNodeType() == Node.ELEMENT_NODE)
{
if(controlNode.getLocalName().equals("myelement");
{
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
#Override
public void skippedComparison(Node nodeIn, Node nodeIn2)
{
//don't care about these events
}
}
Then pass it to the DetailedDiff:
DetailedDiff diff = new DetailedDiff(XMLUnit.compareXML(oldXml, newXml));
diff.overrideDifferenceListener(new IgnoreMyAttributeElements());
List<?> allDifferences = diff.getAllDifferences();
//do something with differences

You might transform both documents first with javax.xml.transform.TransformerFactory so that it only contains the nodes you are interested. Or you could use getControlNodeDetail() and getTestNodeDetail() on Difference to see if the difference applies to the nodes you want.

Related

Java - ArrayList for my Node objects does not follow loop condition for excluding duplicates, but default ArrayList of Strings does

I am learning Java and I am currently trying to make a network analysis program.
I have a network class here:
public class Network {
String name;
ArrayList<Node> nodes;
ArrayList<Edge> edges;
BufferedReader fileObj = null;
String line;
ArrayList nn;
public Network(){
name = "";
nodes = new ArrayList<Node>();
edges = new ArrayList<Edge>();
nn = new ArrayList();
}
public void addnode(Node nodename) {
nodes.add(nodename);
}
public void addedge(Node node1, Node node2) {
Edge newedge = new Edge(node1, node2);
edges.add(newedge);
}
public void readfile(String filename) {
try {
fileObj = new BufferedReader(
new InputStreamReader(
new FileInputStream(filename)));
try {
while((line = fileObj.readLine()) != null) {
String[] splitdata = line.split("\\s+");
Node node1 = new Node(splitdata[0]);
Node node2 = new Node(splitdata[1]);
String nn1 = node1.getname();
String nn2 = node2.getname();
if(!nn.contains(nn1))
nn.add(nn1);
nodes.add(node1);;
if(!nn.contains(nn2))
nn.add(nn2);
nodes.add(node2);;
this.addedge(node1, node2);
}
fileObj.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Reading error " + e);
}
}
catch(FileNotFoundException e) {
System.out.println("File not found.");
}
}
}
And I am trying to read a file of node interactions and add each node entry into the Node ArrayList. However, it does not seem to follow the for loop, adding all entries. The nn ArrayList however, correctly exclude duplicates.
I printed the size of each ArrayList, with the following code:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Network mynetwork = new Network();
mynetwork.readfile("PPInetworkS.txt");
System.out.println(mynetwork.nn.size());
System.out.println(mynetwork.nodes.size());
}
}
This gives a result of 20, and 26, for nn and nodes respectively. Is there something wrong with the for loop, causing the nodes ArrayList to ignore it?
Thanks for all the help!
Please do not forget the curly braces:
if(!nn.contains(nn1)) {
nn.add(nn1);
nodes.add(node1);;
}

Pass a String[] as parameter not working

I have this class now working fine, but I've been struggling with it many hours to end of changing in it on a different logic from my first approach.
public class MyClass {
public static MyClass tablas;
public static String[] GROUPS;
public static String[] ESTATUS
public static String[] CLIENTS;
public void init(){
this.tablas = new MyClass();
this.setGroups();
CLIENTS=this.setAny("/servlets/CLIENTS","page_rows","nombre");
ESTADO_PEDIDO= new String[]{"str1","str2","str3","str4","str5"};
}
private String[] setAny(String sevlet,String bigNode,String smallNode){
String[] ret=null;
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("operation", "4");
parameters.put("avance", "0");
InputStream is = Connection.con.processRequest("GET", sevlet, parameters);
Document dom = null;
try {
dom = UtilesDom.parseXML(is);
NodeList lines = dom.getElementsByTagName(bigNode);
Element el = (Element)lines.item(0);
NodeList nlist = el.getElementsByTagName(smallNode);
ret = new String[nlist.getLength()];
for (int i = 0; i < nlist.getLength(); i++) {
ret[i] = nlist.item(i).getTextContent();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return ret;
}
private void setGroups(){
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("operation", "4");
parameters.put("avance", "0");
InputStream is = Connection.con.processRequest("GET", "/servlets/GROUPS_CLIENTS", parameters);
Document dom = null;
try {
dom = UtilesDom.parseXML(is);
NodeList lines = dom.getElementsByTagName("lines");
Element el = (Element)lines.item(0);
NodeList nlist = el.getElementsByTagName("GROUP");
GROUPS = new String[nlist.getLength()];
for (int i = 0; i < nlist.getLength(); i++) {
GROUPS[i] = nlist.item(i).getTextContent();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
As you can see there is two similar methods setGroups and setAny these are used to fill the Strings[] on top.setGroups was my original method but when I needed different Strings[] thought that a "less hard-coded" and most flexible method would be nice, so I tried this:
private void setAny(String sevlet,String bigNode,String smallNode,String[] which){
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("operation", "4");
parameters.put("avance", "0");
InputStream is = Connection.con.processRequest("GET", sevlet, parameters);
Document dom = null;
try {
dom = UtilesDom.parseXML(is);
NodeList lines = dom.getElementsByTagName(bigNode);
Element el = (Element)lines.item(0);
NodeList nlist = el.getElementsByTagName(smallNode);
which = new String[nlist.getLength()];
for (int i = 0; i < nlist.getLength(); i++) {
which[i] = nlist.item(i).getTextContent();
System.out.println(which[i]);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
Using the call like:
this.setAny("/principal/Clientes","page_rows","nombre",CLIENTS);
also
this.setAny("/principal/Clientes","page_rows","nombre",this.CLIENTS);
and
this.setAny("/principal/Clientes","page_rows","nombre",this.tablas.CLIENTS);
The problem with it is that the String[] passed as parameter (aka CLIENTS) just stay null , and yes at the en of the for loop its populated properly and the console shows what it supposed to.So the question is:
Why String[] CLIENTS cant be populated when passed as a parameter,and just stay as null?
PD: As you may notice English is not my language so please suggest any grammar/redaction/spelling... corrections.
Okay so I'm gonna pretend your parameter is a String[] and not a String here.
Your problem is that once you create a new array with the new operator, your reference changes to that new array. So the old one isn't affected.
So yes, you create a new array and fill it properly, but sadly it won't be CLIENTS. If you do it like in your first example and return the String Array to save it, that will work.
Another option would be to create a static HashMap of String Arrays instead of just three different static String Arrays. Then you can pass the key to the method and just replace the Array at the given key. That way you don't need to work with a return value.
It is null at runtime and the compile dont know about that. It strictly checks the type at compile time it self.
setAny(String sevlet,String bigNode,String smallNode)
That last parameter is a String and you are trying to pass an Array. Probably you need to change the signature as
setAny(String sevlet,String bigNode,String smallNode[])
So that it receives an array.

How to compare 2 XML files and how to fetch the informations like newly Added\Removed elements using XMLUnit

I have 2 xml files with almost similar structure, In these XML files how to fetch the following informations ??
Controls (or Nodes) newly added
Controls (or Nodes) removed and
Control (or Nodes) properties modified.
For your infomration, I tried the following code :
File f1 = new File(inputXMLPath);
File f2= new File(outputXMLPath);
FileReader fr1 = null;
FileReader fr2 = null;
try {
fr1 = new FileReader(f1);
fr2 = new FileReader(f2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
Diff diff = new Diff(fr1, fr2);
System.out.println("Similar? " + diff.similar());
System.out.println("Identical? " + diff.identical());
DetailedDiff detDiff = new DetailedDiff(diff);
detDiff.overrideDifferenceListener(new DifferenceListener() {
#Override
public int differenceFound(Difference diff) {
if (diff.getId() == DifferenceConstants.CHILD_NODELIST_SEQUENCE_ID
|| diff.getId() == DifferenceConstants.CHILD_NODELIST_LENGTH_ID) {
return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
return RETURN_ACCEPT_DIFFERENCE;
}
#Override
public void skippedComparison(Node arg0, Node arg1) { }
});
List differences = detDiff.getAllDifferences();
for (Object object : differences) {
Difference difference = (Difference)object;
System.out.println("***********************");
System.out.println(difference);
System.out.println("***********************");
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
[EDIT: added note about setCompareUnmatched and example code]
I think you want to react to CHILD_NODE_NOT_FOUND Differences that XMLUnit 1.x will emit if you use XMLUnit.setCompareUnmatched(false).
If the control node of the Difference is null, the node was added - if the test node is null it was removed. Any other difference is a change to a Node that XMLUnit thinks is present on either side.
For example
FileReader fr1 = new FileReader(f1);
FileReader fr2 = new FileReader(f2);
XMLUnit.setCompareUnmatched(false);
Diff diff = new Diff(fr1, fr2);
System.out.println("Similar? " + diff.similar());
System.out.println("Identical? " + diff.identical());
DetailedDiff detDiff = new DetailedDiff(diff);
detDiff.overrideDifferenceListener(new DifferenceListener() {
#Override
public int differenceFound(Difference diff) {
if (diff.getId() == DifferenceConstants.CHILD_NODELIST_SEQUENCE_ID
|| diff.getId() == DifferenceConstants.CHILD_NODELIST_LENGTH_ID) {
return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
return RETURN_ACCEPT_DIFFERENCE;
}
#Override
public void skippedComparison(Node arg0, Node arg1) { }
});
List differences = detDiff.getAllDifferences();
for (Object object : differences) {
Difference difference = (Difference)object;
System.out.println("***********************");
if (difference.getId() == DifferenceConstants.CHILD_NODE_NOT_FOUND_ID) {
if (difference.getControlNodeDetail().getNode() == null) {
System.out.println("Node was added");
} else {
System.out.println("Node was removed");
}
}
System.out.println("***********************");
}
will lead to something like
***********************
Expected presence of child node 'baz' but was 'null' - comparing <baz...> at /foo[1]/baz[1] to at null
Node was removed
***********************
***********************
Expected presence of child node 'null' but was 'xyzzy' - comparing at null to <xyzzy...> at /foo[1]/xyzzy[1]
Node was added
***********************

Java retrieve data from sqlite return Objects instead of values

I'm trying to retrieve some data from my Db (I'm using SQLite) using DAO
public class ClassSectionDAO implements IClassSectionDAO{
#Override
public void selectAllClassSection() {
d = new DBManager();
sqliteQuery = new SqliteQueries();
d.executeQuery(sqliteQuery.selectAllFrom("classSection"));
try{
while(d.getResultSet().next()){
ClassSection classSection = new ClassSection();
classSection.setClassSectionId(d.getResultSet().getString("classSectionId"));
classSection.setSchoolClassCode(d.getResultSet().getString("schoolClassCode"));
classSection.setClassSectionNumber(d.getResultSet().getInt("classSectionNumber"));
classSection.setClassSectionAvailability(d.getResultSet().getString("classSectionAvailability"));
classSectionList.add(classSection);
System.out.println("classSectionList: " + classSectionList);
}
}
catch(Exception e){
Logger.getLogger(ClassSectionDAO.class.getName()).log(Level.SEVERE, null, e);
classSectionList = null;
}
finally{
d.closeDatabaseConnection();
}
}
}
All I'm getting is a list of objects like
classSectionList: [entities.classSection.ClassSection#19ccf6d, entities.classSection.ClassSection#1faf0e7, entities.classSection.ClassSection#1cf8409]
What should I do in order to get the values instead?
PS: If you want to see more code, let me know
I think you just made a typo, as you already said in your question: I get a list of Objects (of type ClassSection). That's clear because you print the list of Objects.
If you want to do it in the while loop (print immediately the value for every result), just change the last line in the loop to:
System.out.println("classSectionList: " + classSection.getSchoolClassCode());
If you want to print the values of all results (after all results are processed), just add Michaƫl's solution after the wile loop.
for(ClassSection c : classSectionList) {
System.out.println(c.getSchoolClassCode());
// print other attributes
}
EDIT :
Firt solution :
public class ClassSectionDAO implements IClassSectionDAO{
#Override
public void selectAllClassSection() {
d = new DBManager();
sqliteQuery = new SqliteQueries();
d.executeQuery(sqliteQuery.selectAllFrom("classSection"));
try{
while(d.getResultSet().next()){
ClassSection classSection = new ClassSection();
classSection.setClassSectionId(d.getResultSet().getString("classSectionId"));
classSection.setSchoolClassCode(d.getResultSet().getString("schoolClassCode"));
classSection.setClassSectionNumber(d.getResultSet().getInt("classSectionNumber"));
classSection.setClassSectionAvailability(d.getResultSet().getString("classSectionAvailability"));
classSectionList.add(classSection);
// Solution of ProgrammingIsAwsome
System.out.println("classSectionList: " + classSection.getSchoolClassCode());
}
}
catch(Exception e){
Logger.getLogger(ClassSectionDAO.class.getName()).log(Level.SEVERE, null, e);
classSectionList = null;
}
finally{
d.closeDatabaseConnection();
}
}
}
Second solution :
public class ClassSectionDAO implements IClassSectionDAO{
#Override
public void selectAllClassSection() {
d = new DBManager();
sqliteQuery = new SqliteQueries();
d.executeQuery(sqliteQuery.selectAllFrom("classSection"));
try{
while(d.getResultSet().next()){
ClassSection classSection = new ClassSection();
classSection.setClassSectionId(d.getResultSet().getString("classSectionId"));
classSection.setSchoolClassCode(d.getResultSet().getString("schoolClassCode"));
classSection.setClassSectionNumber(d.getResultSet().getInt("classSectionNumber"));
classSection.setClassSectionAvailability(d.getResultSet().getString("classSectionAvailability"));
classSectionList.add(classSection);
}
// Print the list after the while
for(ClassSection c : classSectionList) {
System.out.println(c.getSchoolClassCode());
// print other attributes
}
}
catch(Exception e){
Logger.getLogger(ClassSectionDAO.class.getName()).log(Level.SEVERE, null, e);
classSectionList = null;
}
finally{
d.closeDatabaseConnection();
}
}
}

Creating stub for dependence class's under test

Good day, everyone! I have a little question about testing and generating a stub for dependence through reflection. So let's assume I have a class named UnderTest:
class UnderTest{
/*field*/
SomeLogic someLogic;
/*method, that i testing*/
List<MyObject> getCalculatedObjects(params) {/*logic,based on result getSomeStuff of someLogic*/ }
}
class SomeLogic {
List<String> getSomeStuff(String param) { /*Some complex and slow code, actually don't want test this code, and want to use some reflection invocation handler*/ }
}
For me it's important to not change legacy code, which doesn't design for testing. And i don't have any reason, except testing to make SomeLogic as an interface and so on.
I can't remember how to handle method invocation of someLogic using reflection. But google search isn't helping me.
Class MainAPI is... main api of my module. NetworkProvider long open stream operation, that's why i want to stub it, on my local files. But don't using directly reference on NetworkProvider. Again sorry for my English.
public class MainAPI {
private final XPath xPath;
private final ItemParser itemParser;
private final ListItemsParser listItemsParser;
private final DateParser dateParser;
private final HtmlCleanUp htmlCleanUp;
private final NetworkProvider networkProvider;
public MainAPI(XPath xPath, ItemParser itemParser, ListItemsParser listItemsParser, DateParser dateParser, HtmlCleanUp htmlCleanUp, NetworkProvider networkProvider) {
this.xPath = xPath;
this.itemParser = itemParser;
this.listItemsParser = listItemsParser;
this.dateParser = dateParser;
this.htmlCleanUp = htmlCleanUp;
this.networkProvider = networkProvider;
}
public MainAPI() throws XPathExpressionException, IOException {
dateParser = new DateParser();
xPath = XPathFactory.newInstance().newXPath();
networkProvider = new NetworkProvider();
listItemsParser = new ListItemsParser(xPath, dateParser, item -> true);
itemParser = new ItemParser(xPath, dateParser, networkProvider);
htmlCleanUp = new HtmlCleanUpByCleaner();
}
public List<Item> getItemsFromSessionParsing(SessionParsing sessionParsing) {
listItemsParser.setCondition(sessionParsing.getFilter());
List<Item> result = new ArrayList<>();
Document cleanDocument;
InputStream inputStream;
for (int currentPage = sessionParsing.getStartPage(); currentPage <= sessionParsing.getLastPage(); currentPage++) {
try {
inputStream = networkProvider.openStream(sessionParsing.getUrlAddressByPageNumber(currentPage));
} catch (MalformedURLException e) {
e.printStackTrace();
break;
}
cleanDocument = htmlCleanUp.getCleanDocument(inputStream);
List<Item> list = null;
try {
list = listItemsParser.getList(cleanDocument);
} catch (XPathExpressionException e) {
e.printStackTrace();
break;
}
for (Item item : list) {
inputStream = null;
try {
inputStream = networkProvider.openStream("http://www.avito.ru" + item.getUrl());
} catch (MalformedURLException e) {
e.printStackTrace();
break;
}
cleanDocument = htmlCleanUp.getCleanDocument(inputStream);
try {
item.setDescription(itemParser.getDescription(cleanDocument));
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
result.addAll(list);
}
return result;
}
}
public class NetworkProvider {
private final ListCycleWrapper<Proxy> proxyList;
public NetworkProvider(List<Proxy> proxyList) {
this.proxyList = new ListCycleWrapper<>(proxyList);
}
public NetworkProvider() throws XPathExpressionException, IOException {
this(new ProxySiteParser().getProxyList(new HtmlCleanUpByCleaner().getCleanDocument(new URL("http://www.google-proxy.net").openStream())));
}
public int getSizeOfProxy() {
return proxyList.size();
}
public InputStream openStream(String urlAddress) throws MalformedURLException {
URL url = new URL(urlAddress);
while (!proxyList.isEmpty()) {
URLConnection con = null;
try {
con = url.openConnection(proxyList.getNext());
con.setConnectTimeout(6000);
con.setReadTimeout(6000);
return con.getInputStream();
} catch (IOException e) {
proxyList.remove();
}
}
return null;
}
}
All the dependencies of your class to tests are injectable using its constructor, so there shouldn't be any problem to stub these dependencies and injecting the stubs. You don't even need reflection. For example, using Mockito:
NetworkProvider stubbedNetworkProvider = mock(NetworkProvider.class);
MainAPI mainApi = new MainAPI(..., stubbedNetworkProvider);
You can also write a stub by yourself if you want:
NetworkProvider stubbedNetworkProvider = new NetworkProvider(Collections.emptyList()) {
// TODO override the methods to stub
};
MainAPI mainApi = new MainAPI(..., stubbedNetworkProvider);

Categories