merged tag ooo/DEV300_m102
[LibreOffice.git] / xmerge / workben / XmlDiff.java
blobe41dbbb6b9b00449c13362477b2abf6fcc97e8ad
1 /************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 import java.io.FileWriter;
29 import java.io.InputStream;
30 import java.io.FileInputStream;
31 import java.io.BufferedInputStream;
32 import java.io.BufferedWriter;
33 import java.io.IOException;
34 import java.io.FileNotFoundException;
35 import java.io.OutputStream;
36 import java.io.OutputStreamWriter;
37 import java.io.Writer;
38 import java.io.PrintWriter;
39 import java.util.Vector;
40 import java.util.Properties;
42 import javax.xml.parsers.DocumentBuilderFactory;
43 import javax.xml.parsers.DocumentBuilder;
44 import javax.xml.parsers.ParserConfigurationException;
46 import org.w3c.dom.Node;
47 import org.w3c.dom.Document;
48 import org.w3c.dom.NodeList;
49 import org.xml.sax.SAXException;
50 import org.xml.sax.SAXParseException;
51 /**
52 * This class will diff 2 Xml files.
54 * @author Stephen Mak
57 public final class XmlDiff {
59 private static final String PROPSFILE = "XmlDiff.properties";
60 private static final String FILE1 = "XmlDiff.file1";
61 private static final String FILE2 = "XmlDiff.file2";
62 private static final String OUTPUT= "XmlDiff.output";
63 private static final String IGNORE_TAGS= "XmlDiff.tags";
65 private Properties props_ = null;
66 private static PrintWriter writer_ = null;
67 private String[] tags_ = null;
68 private String file1_ = null;
69 private String file2_ = null;
71 /**
72 * Constructor. Load the properties file.
75 public XmlDiff() throws IOException {
77 Class c = this.getClass();
78 InputStream is = c.getResourceAsStream(PROPSFILE);
79 BufferedInputStream bis = new BufferedInputStream(is);
80 props_ = new Properties();
81 props_.load(bis);
82 bis.close();
84 String file1 = props_.getProperty(FILE1, "");
85 String file2 = props_.getProperty(FILE2, "");
86 String tagsString = props_.getProperty(IGNORE_TAGS, "");
87 String output = props_.getProperty("debug.output", "System.out");
88 setOutput(output);
89 tags_ = parseTags(tagsString);
92 /**
93 * diff 2 xml, but overwrite the property file's file1/2 setting with
94 * the input argument
96 public boolean diff(String file1, String file2) throws IOException {
97 file1_ = file1;
98 file2_ = file2;
99 return diff();
102 public boolean diff() throws IOException {
104 boolean result = false;
106 writer_.println("parsing "+ file1_ + "...");
107 // parse the Xml file
108 Document doc1 = parseXml(file1_);
110 writer_.println("parsing "+ file1_ + "...");
111 Document doc2 = parseXml(file2_);
113 if (doc1 != null && doc2 != null) {
114 writer_.println("diffing "+ file1_ + " & " + file2_ + "...");
115 result = compareNode(doc1, doc2);
117 return result;
120 private void diffLog(String errMsg, Node node1, Node node2) {
122 String node1Str = "";
123 String node2Str = "";
125 if (node1 != null) {
126 node1Str = "[Type]:" + nodeInfo(node1) +
127 " [Name]:" + node1.getNodeName();
128 if (node1.getNodeValue() != null)
129 node1Str += " [Value]:" + node1.getNodeValue();
132 if (node2 != null) {
133 node2Str = "[Type]:" + nodeInfo(node2) +
134 " [Name]:" + node2.getNodeName();
135 if (node2.getNodeValue() != null)
136 node2Str += " [Value]:" + node2.getNodeValue();
139 writer_.println(errMsg);
140 writer_.println(" Node1 - " + node1Str);
141 writer_.println(" Node2 - " + node2Str);
144 private String nodeInfo(Node node) {
146 String str = null;
147 switch (node.getNodeType()) {
149 case Node.ELEMENT_NODE:
150 str = "ELEMENT";
151 break;
152 case Node.ATTRIBUTE_NODE:
153 str = "ATTRIBUTE";
154 break;
155 case Node.TEXT_NODE:
156 str = "TEXT";
157 break;
158 case Node.CDATA_SECTION_NODE:
159 str = "CDATA_SECTION";
160 break;
161 case Node.ENTITY_REFERENCE_NODE:
162 str = "ENTITY_REFERENCE";
163 break;
164 case Node.ENTITY_NODE:
165 str = "ENTITY";
166 break;
167 case Node.PROCESSING_INSTRUCTION_NODE:
168 str = "PROCESSING_INSTRUCTION";
169 break;
170 case Node.COMMENT_NODE:
171 str = "COMMENT";
172 break;
173 case Node.DOCUMENT_NODE:
174 str = "DOCUMENT";
175 break;
176 case Node.DOCUMENT_TYPE_NODE:
177 str = "DOCUMENT_TYPE";
178 break;
179 case Node.DOCUMENT_FRAGMENT_NODE:
180 str = "DOCUMENT_FRAGMENT";
181 break;
182 case Node.NOTATION_NODE:
183 str = "NOTATION";
184 break;
186 return str;
189 private boolean ignoreTag(String nodeName) {
192 if (tags_ != null) {
193 for (int i = 0; i < tags_.length; i++) {
194 if (tags_[i].equals(nodeName))
195 return true;
198 return false;
201 // for future use if we want to compare attributes
202 private boolean attributesEqual(Node node1, Node node2) {
203 return true;
206 private boolean compareNode(Node node1, Node node2) {
207 boolean equal = false;
209 while (true) {
211 if (node1 == null && node2 == null) {
212 equal = true;
213 break;
214 } else if (node1 == null || node2 == null) {
215 diffLog("DIFF: one of the node is null", node1, node2);
216 break;
219 if (node1.getNodeType() != node2.getNodeType()) {
220 diffLog("DIFF: nodetype is different", node1, node2);
221 break;
224 if (node1.getNodeName() == null && node2.getNodeName() == null) {
225 // empty
226 } else if (node1.getNodeName() == null ||
227 node2.getNodeName() == null) {
228 diffLog("DIFF: one of the nodeName is null", node1, node2);
229 break;
230 } else if (!node1.getNodeName().equals(node2.getNodeName())) {
231 diffLog("DIFF: nodeName is different", node1, node2);
232 break;
235 if (ignoreTag(node1.getNodeName())) {
236 diffLog("DIFF: Some tag(s) is ignored", node1, node2);
237 equal = true;
238 break;
241 if (node1.getNodeValue() == null && node2.getNodeValue() == null) {
242 // empty
243 } else if (node1.getNodeValue() == null ||
244 node2.getNodeValue() == null) {
245 diffLog("DIFF: one of the nodevalue is null", node1, node2);
246 break;
247 } else if (!node1.getNodeValue().equals(node2.getNodeValue())) {
248 diffLog("DIFF: nodeValue is different", node1, node2);
249 break;
252 // try to compare attributes if necessary
253 if (!attributesEqual(node1, node2))
254 break;
256 NodeList node1Children = node1.getChildNodes();
257 NodeList node2Children = node2.getChildNodes();
259 // number of children have to be the same
260 if (node1Children == null && node2Children == null) {
261 equal = true;
262 break;
265 if (node1Children == null || node2Children == null) {
266 diffLog("DIFF: one node's children is null", node1, node2);
267 break;
270 if (node1Children.getLength() != node2Children.getLength()) {
271 diffLog("DIFF: num of children is different", node1, node2);
272 break;
275 // compare all the childrens
276 equal = true;
278 for (int i = 0; i < node1Children.getLength(); i++) {
279 if (!compareNode(node1Children.item(i),
280 node2Children.item(i))) {
281 equal = false;
282 break;
285 break;
288 return equal;
291 private Document parseXml (String filename) throws IOException {
293 Document w3cDocument = null;
295 FileInputStream fis;
297 try {
298 fis = new FileInputStream(filename);
299 } catch (FileNotFoundException ex) {
300 ex.printStackTrace(writer_);
301 writer_.println(ex.getMessage());
302 return w3cDocument;
305 /** factory for DocumentBuilder objects */
306 DocumentBuilderFactory factory = null;
307 factory = DocumentBuilderFactory.newInstance();
308 factory.setNamespaceAware(true);
309 factory.setValidating(false);
311 /** DocumentBuilder object */
312 DocumentBuilder builder = null;
314 try {
315 builder = factory.newDocumentBuilder();
316 } catch (ParserConfigurationException ex) {
317 ex.printStackTrace(writer_);
318 writer_.println(ex.getMessage());
319 return null;
323 builder.setErrorHandler(
324 new org.xml.sax.ErrorHandler() {
325 // ignore fatal errors (an exception is guaranteed)
326 public void fatalError(SAXParseException e)
327 throws SAXException {
328 throw e;
331 public void error(SAXParseException e)
332 throws SAXParseException {
333 // make sure validation error is thrown.
334 throw e;
337 public void warning(SAXParseException e)
338 throws SAXParseException {
343 try {
344 w3cDocument = builder.parse(fis);
345 w3cDocument.getDocumentElement().normalize();
346 } catch (SAXException ex) {
347 ex.printStackTrace(writer_);
348 writer_.println(ex.getMessage());
349 return w3cDocument;
352 return w3cDocument;
355 private String [] parseTags(String tagsString) {
356 Vector tagsVector = new Vector();
357 if (tagsString.length() == 0)
358 return null;
360 int start = 0;
361 int end = 0;
362 // break the tag string into a vector of strings by words
363 for (end = tagsString.indexOf(" ", start);
364 end != -1 ;
365 start = end + 1, end = tagsString.indexOf(" ", start)) {
366 tagsVector.add(tagsString.substring(start,end));
369 tagsVector.add(tagsString.substring(start,tagsString.length()));
371 // convert the vector to array
372 String[] tags= new String[tagsVector.size()];
373 tagsVector.copyInto(tags);
375 return tags;
380 * Set the output to the specified argument.
381 * This method is only used internally to prevent
382 * invalid string parameter.
384 * @param str output specifier
386 private static void setOutput(String str) {
388 if (writer_ == null) {
390 if (str.equals("System.out")) {
392 setOutput(System.out);
394 } else if (str.equals("System.err")) {
396 setOutput(System.err);
398 } else {
400 try {
402 setOutput(new FileWriter(str));
404 } catch (IOException e) {
406 e.printStackTrace(System.err);
413 * Set the output to an OutputStream object.
415 * @param stream OutputStream object
418 private static void setOutput(OutputStream stream) {
420 setOutput(new OutputStreamWriter(stream));
424 * Set the Writer object to manage the output.
426 * @param w Writer object to write out
429 private static void setOutput(Writer w) {
431 if (writer_ != null) {
433 writer_.close();
436 writer_ = new PrintWriter(new BufferedWriter(w), true);
439 public static void main(String args[]) throws IOException {
441 if (args.length != 0 && args.length != 2) {
442 System.out.println("Usage: XmlDiff [<file1> <file2>].");
443 return;
446 XmlDiff xmldiff = new XmlDiff();
448 boolean same = false;
449 if (args.length == 2) {
450 same = xmldiff.diff(args[0], args[1]);
451 } else {
452 same = xmldiff.diff();
455 System.out.println("Diff result: " + same);