protected void queryPair(File inputFile, File outputFile)
			throws IOException, SAXException, LSHException {
		if (!inputFile.isFile()) {
			throw new IOException(inputFile.getAbsolutePath() + " is not an XML file");
		}
		if (outputFile.isFile()) {
			Msg.info(this, "Overwriting file " + outputFile.getAbsolutePath());
			outputFile.delete();
		}
		establishQueryServerConnection(true);
		QueryPair query = new QueryPair();
		query.pairs = new ArrayList<PairInput>();
		ErrorHandler handler = SpecXmlUtils.getXmlHandler();
		XmlPullParser parser = XmlPullParserFactory.create(inputFile, handler, false);
		parser.start("querypair");

		try (FileWriter writer = new FileWriter(outputFile)) {
			writer.append("<responsepair>\n");
			ResponsePair.Accumulator accumulator = new ResponsePair.Accumulator();
			ResponsePair finalResponse = new ResponsePair();
			int count = readQueryPairs(parser, 20, query.pairs);
			while (count != 0) {
				ResponsePair responsePair = query.execute(querydb);
				if (responsePair == null) {
					BSimError lastError = querydb.getLastError();
					throw new LSHException(lastError.message);
				}
				for (PairNote note : responsePair.notes) {
					note.saveXml(writer);
				}
				finalResponse.scale = responsePair.scale;
				accumulator.merge(responsePair);
				query.pairs.clear();
				query.clearResponse();
				count = readQueryPairs(parser, 20, query.pairs);
			}
			parser.end();
			finalResponse.fillOutStatistics(accumulator);
			finalResponse.saveXmlTail(writer);
			writer.append("</responsepair>\n");
		}
	}
Compares pairs of functions specified in an input (XML) file, and writes
the results to an output file.

@param inputFile input XML file
@param outputFile output XML file
@throws IOException if there is a problem establishing the server connection
@throws SAXException if an XML parse error occurs
@throws LSHException if there is a problem querying the database
Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java