bool XMLDocument::isElementEqual(SimTK::Xml::Element& elt1, SimTK::Xml::Element& elt2, double toleranceForDoubles) { SimTK::String s1,s2; elt1.writeToString(s1); elt2.writeToString(s2); SimTK::Xml::attribute_iterator att1 = elt1.attribute_begin(); SimTK::Xml::attribute_iterator att2 = elt2.attribute_begin(); // Handle different # attributes if ( (att1 == elt1.attribute_end() && att2 != elt2.attribute_end()) || (att1 != elt1.attribute_end() && att2 == elt2.attribute_end()) ){ cout << "Number of attributes is different, element " << elt1.getElementTag() << endl; return false; } bool equal =true; // Same size attributes including none for(att1 = elt1.attribute_begin(); att1 != elt1.attribute_end() && equal; att1++, att2++){ equal = (att1->getName() == att2->getName()); equal = equal && (att1->getValue() == att2->getValue()); if (!equal) { cout << "Attribute " << att1->getName() << " is different " << att1->getValue() << "vs." << att2->getValue() << endl; } } if (!equal) return false; // Attributes match now children SimTK::Array_<SimTK::Xml::Element> elts1 = elt1.getAllElements(); SimTK::Array_<SimTK::Xml::Element> elts2 = elt2.getAllElements(); if (elts1.size() != elts2.size()){ cout << "Different number of children for Element " << elt1.getElementTag() << endl; equal = false; } if (!equal) return false; // Recursively compare Elements unless Value Elements in that case do direct compare for(unsigned it = 0; it < elts1.size() && equal; it++){ SimTK::String elt1Tag = elts1[it].getElementTag(); cout << "Compare " << elt1Tag << endl; SimTK::Xml::element_iterator elt2_iter = elt2.element_begin(elt1Tag); if (elt2_iter==elt2.element_end()){ cout << "Element " << elt1Tag << " was not found in reference document" << endl; equal = false; break; } bool value1 = elts1[it].isValueElement(); bool value2 = elt2_iter->isValueElement(); equal = (value1 == value2); if (!equal){ cout << elts1[it].getElementTag() << " is different. One is Value Element the other isn't" << endl; return false; } if (value1){ // We should check if this's a double or array of doubles in that case we can getValueAs<double> anbd try { SimTK::Array_<double> v1, v2; elts1[it].getValueAs(v1); elt2_iter->getValueAs(v2); for(unsigned ix=0; ix<v1.size() && equal; ix++) equal = (std::fabs(v1[ix]-v2[ix]) < toleranceForDoubles); } catch(...){ equal = (elts1[it].getValue() == elt2_iter->getValue()); } } else // recur equal = isElementEqual(elts1[it], elts2[it], toleranceForDoubles); if (!equal){ cout << elts1[it].getElementTag() << " is different" << endl; SimTK::String pad; elts1[it].writeToString(pad); cout << pad << endl; cout << "------------------- vs. ------" << endl; elts2[it].writeToString(pad); cout << pad << endl; return equal; } } return equal; }