You can subscribe to this list here.
2007 |
Jan
|
Feb
(3) |
Mar
(18) |
Apr
(39) |
May
(15) |
Jun
(12) |
Jul
(3) |
Aug
(23) |
Sep
|
Oct
(1) |
Nov
(1) |
Dec
(3) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(21) |
Feb
(23) |
Mar
(33) |
Apr
(8) |
May
(1) |
Jun
(22) |
Jul
|
Aug
(1) |
Sep
(1) |
Oct
(6) |
Nov
|
Dec
(11) |
2009 |
Jan
(5) |
Feb
|
Mar
(2) |
Apr
(24) |
May
(36) |
Jun
(18) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(3) |
Nov
(1) |
Dec
|
2010 |
Jan
(5) |
Feb
(3) |
Mar
|
Apr
(15) |
May
(24) |
Jun
(11) |
Jul
(8) |
Aug
(34) |
Sep
(42) |
Oct
|
Nov
|
Dec
|
2011 |
Jan
(13) |
Feb
(32) |
Mar
(35) |
Apr
(31) |
May
(33) |
Jun
(30) |
Jul
(32) |
Aug
(31) |
Sep
(30) |
Oct
(31) |
Nov
(32) |
Dec
(31) |
2012 |
Jan
(35) |
Feb
(31) |
Mar
(31) |
Apr
(30) |
May
(31) |
Jun
(34) |
Jul
(23) |
Aug
(30) |
Sep
(30) |
Oct
(29) |
Nov
(30) |
Dec
(32) |
2013 |
Jan
(25) |
Feb
(39) |
Mar
(1) |
Apr
(18) |
May
(1) |
Jun
|
Jul
(1) |
Aug
(20) |
Sep
(41) |
Oct
(32) |
Nov
(9) |
Dec
(31) |
2014 |
Jan
(31) |
Feb
(30) |
Mar
(34) |
Apr
(60) |
May
(31) |
Jun
(28) |
Jul
(32) |
Aug
(28) |
Sep
(26) |
Oct
(32) |
Nov
(43) |
Dec
(115) |
2015 |
Jan
(106) |
Feb
(101) |
Mar
(51) |
Apr
(32) |
May
(63) |
Jun
(18) |
Jul
|
Aug
(18) |
Sep
|
Oct
(1) |
Nov
(84) |
Dec
(63) |
2016 |
Jan
(26) |
Feb
(17) |
Mar
(104) |
Apr
(30) |
May
(6) |
Jun
(30) |
Jul
|
Aug
|
Sep
|
Oct
(3) |
Nov
(48) |
Dec
(22) |
2017 |
Jan
(15) |
Feb
(29) |
Mar
(43) |
Apr
(29) |
May
(25) |
Jun
(28) |
Jul
(62) |
Aug
(35) |
Sep
(35) |
Oct
(72) |
Nov
(10) |
Dec
(4) |
2018 |
Jan
(7) |
Feb
(4) |
Mar
|
Apr
(46) |
May
(20) |
Jun
(12) |
Jul
(9) |
Aug
(42) |
Sep
(4) |
Oct
(17) |
Nov
(32) |
Dec
(31) |
2019 |
Jan
(21) |
Feb
(14) |
Mar
|
Apr
(74) |
May
(25) |
Jun
(43) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
(2) |
Nov
|
Dec
(10) |
2020 |
Jan
(1) |
Feb
|
Mar
(26) |
Apr
(8) |
May
(62) |
Jun
(4) |
Jul
(25) |
Aug
|
Sep
(21) |
Oct
(24) |
Nov
(26) |
Dec
(9) |
2021 |
Jan
|
Feb
(4) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(1) |
Oct
(11) |
Nov
(1) |
Dec
(12) |
2022 |
Jan
(47) |
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(14) |
2023 |
Jan
(3) |
Feb
|
Mar
(60) |
Apr
(9) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2024 |
Jan
(5) |
Feb
|
Mar
|
Apr
(10) |
May
(1) |
Jun
|
Jul
|
Aug
(17) |
Sep
(2) |
Oct
|
Nov
|
Dec
(1) |
2025 |
Jan
|
Feb
|
Mar
(88) |
Apr
(64) |
May
(47) |
Jun
(20) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <bo...@us...> - 2007-03-28 16:19:24
|
Revision: 161 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=161&view=rev Author: bodewig Date: 2007-03-28 09:19:23 -0700 (Wed, 28 Mar 2007) Log Message: ----------- I know this fails for some documents with DOCTYPEs, commit it now anyway: refactor Validator support for InputStreams Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java Added Paths: ----------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeConstants.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeInputStream.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeSupport.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DoctypeInputStream.java Added: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeConstants.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeConstants.java (rev 0) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeConstants.java 2007-03-28 16:19:23 UTC (rev 161) @@ -0,0 +1,45 @@ +/* +****************************************************************** +Copyright (c) 2001, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + +package org.custommonkey.xmlunit; + +interface DoctypeConstants { + String DOCTYPE_OPEN_DECL = "<!"; + int DECL_LENGTH = DOCTYPE_OPEN_DECL.length(); + String DOCTYPE_CLOSE_DECL = ">"; + String DOCTYPE = "DOCTYPE "; + String SYSTEM = " SYSTEM \""; +} \ No newline at end of file Property changes on: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeConstants.java ___________________________________________________________________ Name: svn:executable + * Name: svn:eol-style + native Added: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeInputStream.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeInputStream.java (rev 0) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeInputStream.java 2007-03-28 16:19:23 UTC (rev 161) @@ -0,0 +1,216 @@ +/* +****************************************************************** +Copyright (c) 2001, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + +package org.custommonkey.xmlunit; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; + +/** + * Adapts the marked-up content in a source InputStream to specify that it + * conforms to a different DTD. + * Combines InputStream semantics with the ability to specify a target doctype + * for a byte stream containing XML markup. + * Used by Validator class to wrap an InputStrea, when performing validation of a + * document against a DTD. + * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a> + */ +public class DoctypeInputStream extends InputStream { + private final InputStream wrappedStream; + + private static final byte[] DOCTYPE_BYTES = { + 'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ' + }; + + private byte[] readAheadBeforeDeclBuffer = null; + private int readAheadBeforeDeclOffset = 0; + private byte[] readAheadAfterDeclBuffer = null; + private int readAheadAfterDeclOffset = 0; + + private final DoctypeSupport docType; + private boolean writeDecl = false; + + + /** + * Create an InputStream whose XML content is provided by the + * originalSource with the exception of the DOCTYPE which is + * provided by the doctypeName and systemID. + * @param originalSource + * @param doctypeName + * @param systemID + */ + public DoctypeInputStream(InputStream originalSource, String doctypeName, + String systemID) { + wrappedStream = originalSource instanceof BufferedInputStream + ? originalSource : new BufferedInputStream(originalSource); + docType = new DoctypeSupport(doctypeName, systemID); + } + + /** + * Read DOCTYPE-replaced content from the wrapped Reader + */ + public int read() throws IOException { + int nextByte = -1; + + if (writeDecl) { + // currently writing our own DOCTYPE declaration + nextByte = docType.read(); + if (nextByte == -1) { + writeDecl = false; + } else { + return nextByte; + } + } + + if (readAheadBeforeDeclBuffer != null) { + // in part of original document before our DOCTYPE - this + // has already been read + nextByte = readAheadBeforeDeclBuffer[readAheadBeforeDeclOffset++]; + if (readAheadBeforeDeclOffset >= readAheadBeforeDeclBuffer.length) { + readAheadBeforeDeclBuffer = null; + writeDecl = true; + } + } else if (!docType.hasBeenRead()) { + // DOCTYPE not written, yet, need to see where it should go + + // read ahead until we find a good place to insert the doctype, + // store bytes in readAheadBuffers + ByteArrayOutputStream beforeDecl = new ByteArrayOutputStream(); + ByteArrayOutputStream afterDecl = new ByteArrayOutputStream(); + int current; + boolean ready = false; + while (!ready && (current = wrappedStream.read()) != -1) { + byte c = (byte) current; + if (c >= 0 && Character.isWhitespace((char) c)) { + beforeDecl.write(c); + } else if (c == '<') { + // could be XML declaration, comment, PI, DOCTYPE + // or the first element + byte[] elementOrDeclOr = readUntilCloseCharacterIsReached(); + if (elementOrDeclOr.length > 0) { + if (elementOrDeclOr[0] == '?') { + // XML declaration or PI + beforeDecl.write('<'); + beforeDecl.write(elementOrDeclOr, 0, + elementOrDeclOr.length); + } else if (elementOrDeclOr[0] != '!') { + // first element + afterDecl.write('<'); + afterDecl.write(elementOrDeclOr, 0, + elementOrDeclOr.length); + ready = true; + } else { + // comment or doctype + if (indexOfDoctype(elementOrDeclOr) == -1) { + afterDecl.write('<'); + afterDecl.write(elementOrDeclOr, 0, + elementOrDeclOr.length); + } // else swallow old declaration + ready = true; + } + } + + } else { + afterDecl.write(c); + ready = true; + } + } + readAheadBeforeDeclBuffer = beforeDecl.size() > 0 + ? beforeDecl.toByteArray() : null; + readAheadAfterDeclBuffer = afterDecl.size() > 0 + ? afterDecl.toByteArray() : null; + writeDecl = (readAheadBeforeDeclBuffer == null); + return read(); + } else if (readAheadAfterDeclBuffer != null) { + // in part of original document read ahead after our DOCTYPE + nextByte = readAheadAfterDeclBuffer[readAheadAfterDeclOffset++]; + if (readAheadAfterDeclOffset >= readAheadAfterDeclBuffer.length) { + readAheadAfterDeclBuffer = null; + } + } else { + nextByte = wrappedStream.read(); + } + return nextByte; + } + + private byte[] readUntilCloseCharacterIsReached() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int byteRead = -1; + int openCount = 1; + while (openCount > 0 && (byteRead = wrappedStream.read()) != -1) { + byte c = (byte) byteRead; + baos.write(c); + if (c == '<') { + openCount++; + } + if (c == '>') { + openCount--; + } + } + return baos.toByteArray(); + } + + public void close() throws IOException { + wrappedStream.close(); + } + + /** + * Could be faster when searching from the other end, but should do. + */ + private static int indexOfDoctype(byte[] b) { + int index = -1; + for (int i = 0; i < b.length - DOCTYPE_BYTES.length + 1; i++) { + if (b[i] == DOCTYPE_BYTES[0]) { + boolean found = false; + int j = 1; + for (; !found && j < DOCTYPE_BYTES.length; j++) { + if (b[i + j] != DOCTYPE_BYTES[j]) { + found = true; + } + } + if (found) { + index = i; + break; + } else { + i += j - 1; + } + } + } + return index; + } +} \ No newline at end of file Property changes on: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeInputStream.java ___________________________________________________________________ Name: svn:executable + * Name: svn:eol-style + native Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java 2007-03-28 04:10:28 UTC (rev 160) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java 2007-03-28 16:19:23 UTC (rev 161) @@ -38,10 +38,7 @@ import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; -import java.io.StringReader; /** * Adapts the marked-up content in a source Reader to specify that it @@ -52,19 +49,19 @@ * document against a DTD. * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a> */ -public class DoctypeReader extends Reader { - private static final String DOCTYPE_OPEN_DECL = "<!"; - private static final int DECL_LENGTH = DOCTYPE_OPEN_DECL.length(); - private static final String DOCTYPE_CLOSE_DECL = ">"; - private static final String DOCTYPE = "DOCTYPE "; - private static final String SYSTEM = " SYSTEM \""; - private final Reader originalSource; +public class DoctypeReader extends Reader implements DoctypeConstants { + + private final Reader originalReader; private final StringBuffer sourceBuffer = new StringBuffer(1024); - private final String doctypeName; - private final String systemId; - private Reader replacementReader; + private char[] readAheadBeforeDeclBuffer = null; + private int readAheadBeforeDeclOffset = 0; + private char[] readAheadAfterDeclBuffer = null; + private int readAheadAfterDeclOffset = 0; + private final DoctypeSupport docType; + private boolean writeDecl = false; + /** * Create a Reader whose XML content is provided by the originalSource with * the exception of the DOCTYPE which is provided by the doctypeName @@ -75,44 +72,20 @@ */ public DoctypeReader(Reader originalSource, String doctypeName, String systemID) { - this.originalSource = originalSource; - this.doctypeName = doctypeName; - this.systemId = systemID; + originalReader = originalSource instanceof BufferedReader + ? originalSource : new BufferedReader(originalSource); + docType = new DoctypeSupport(doctypeName, systemID); } /** - * Create a Reader whose XML content is provided by the originalSource with - * the exception of the DOCTYPE which is provided by the doctypeName - * and systemID. - * @param originalSource - * @param doctypeName - * @param systemID - */ - public DoctypeReader(InputStream originalSource, String encoding, - String doctypeName, String systemID) - throws IOException { - this(encoding != null - ? new InputStreamReader(originalSource, encoding) - : xmlStreamToReader(originalSource), - doctypeName, systemID); - } - - // XXX - we are cheating here, we should read into the source - // stream to see whether the XML decl (if any) specifies the - // encoding and then return an InputStreamReader using the proper - // encoding - private static Reader xmlStreamToReader(InputStream originalSource) - throws IOException { - return new InputStreamReader(originalSource); - } - - /** * @return the content of the original source, without amendments or * substitutions. Safe to call multiple times. * @throws IOException if thrown while reading from the original source + * @deprecated this method is only here for BWC, it is no longer + * used by this class */ protected String getContent() throws IOException { - return getContent(originalSource).toString(); + return obsoleteGetContent(originalReader).toString(); } /** @@ -120,7 +93,8 @@ * @return the contents of the originalSource within a StringBuffer * @throws IOException if thrown while reading from the original source */ - private StringBuffer getContent(Reader originalSource) throws IOException { + private StringBuffer obsoleteGetContent(Reader originalSource) + throws IOException { if (sourceBuffer.length() == 0) { BufferedReader bufferedReader; if (originalSource instanceof BufferedReader) { @@ -152,7 +126,7 @@ * @param withinContent * @return */ - private int findStartDoctype(StringBuffer withinContent) { + private int obsoleteFindStartDoctype(StringBuffer withinContent) { int startAt = -1; char curChar; boolean canInsert = true; @@ -183,6 +157,8 @@ * @param doctypeName * @param systemId * @return the content, after DOCTYPE amendment / addition + * @deprecated this method is only here for BWC, it is no longer + * used by this class */ public String replaceDoctype(StringBuffer withinContent, String doctypeName, String systemId) { @@ -190,7 +166,7 @@ int startDoctype = content.indexOf(DOCTYPE); boolean noCurrentDoctype = false; if (startDoctype == -1) { - startDoctype = findStartDoctype(withinContent); + startDoctype = obsoleteFindStartDoctype(withinContent); noCurrentDoctype = true; } @@ -227,18 +203,6 @@ } /** - * Wrap the DOCTYPE-replaced content in a StringReader - * @return a StringReader from which the DOCTYPE-replaced content can be read - * @throws IOException - */ - private Reader getReplacementReader() throws IOException { - StringBuffer originalContent = getContent(originalSource); - String replacedContent = replaceDoctype(originalContent, - doctypeName, systemId); - return new StringReader(replacedContent); - } - - /** * Read DOCTYPE-replaced content from the wrapped Reader * @param cbuf * @param off @@ -248,17 +212,115 @@ * @throws IOException */ public int read(char cbuf[], int off, int len) throws IOException { - if (replacementReader == null) { - replacementReader = getReplacementReader(); + int startPos = off; + int currentlyRead; + while (off - startPos < len && (currentlyRead = read()) != -1) { + cbuf[off++] = (char) currentlyRead; } - return replacementReader.read(cbuf, off, len); + return off == startPos && len != 0 ? -1 : off - startPos; } /** - * Close the wrapped Reader - * @throws IOException + * Read DOCTYPE-replaced content from the wrapped Reader */ + public int read() throws IOException { + int nextChar = -1; + + if (writeDecl) { + // currently writing our own DOCTYPE declaration + nextChar = docType.read(); + if (nextChar == -1) { + writeDecl = false; + } else { + return nextChar; + } + } + + if (readAheadBeforeDeclBuffer != null) { + // in part of original document before our DOCTYPE - this + // has already been read + nextChar = readAheadBeforeDeclBuffer[readAheadBeforeDeclOffset++]; + if (readAheadBeforeDeclOffset >= readAheadBeforeDeclBuffer.length) { + readAheadBeforeDeclBuffer = null; + writeDecl = true; + } + } else if (!docType.hasBeenRead()) { + // DOCTYPE not written, yet, need to see where it should go + + // read ahead until we find a good place to insert the doctype, + // store characters in readAheadBuffers + StringBuffer beforeDecl = new StringBuffer(); + StringBuffer afterDecl = new StringBuffer(); + int current; + boolean ready = false; + while (!ready && (current = originalReader.read()) != -1) { + char c = (char) current; + if (Character.isWhitespace(c)) { + beforeDecl.append(c); + } else if (c == '<') { + // could be XML declaration, comment, PI, DOCTYPE + // or the first element + String elementOrDeclOr = readUntilCloseCharacterIsReached(); + if (elementOrDeclOr.length() > 0) { + if (elementOrDeclOr.charAt(0) == '?') { + // XML declaration or PI + beforeDecl.append('<').append(elementOrDeclOr); + } else if (elementOrDeclOr.charAt(0) != '!') { + // first element + afterDecl.append('<').append(elementOrDeclOr); + ready = true; + } else { + // comment or doctype + if (elementOrDeclOr.indexOf(DOCTYPE) == -1) { + afterDecl.append('<').append(elementOrDeclOr); + } // else swallow old declaration + ready = true; + } + } + + } else { + afterDecl.append(c); + ready = true; + } + } + readAheadBeforeDeclBuffer = beforeDecl.length() > 0 + ? beforeDecl.toString().toCharArray() + : null; + readAheadAfterDeclBuffer = afterDecl.length() > 0 + ? afterDecl.toString().toCharArray() + : null; + writeDecl = (readAheadBeforeDeclBuffer == null); + return read(); + } else if (readAheadAfterDeclBuffer != null) { + // in part of original document read ahead after our DOCTYPE + nextChar = readAheadAfterDeclBuffer[readAheadAfterDeclOffset++]; + if (readAheadAfterDeclOffset >= readAheadAfterDeclBuffer.length) { + readAheadAfterDeclBuffer = null; + } + } else { + nextChar = originalReader.read(); + } + return nextChar; + } + + private String readUntilCloseCharacterIsReached() throws IOException { + StringBuffer sb = new StringBuffer(); + int characterRead = -1; + int openCount = 1; + while (openCount > 0 && (characterRead = originalReader.read()) != -1) { + char c = (char) characterRead; + sb.append(c); + if (c == '<') { + openCount++; + } + if (c == '>') { + openCount--; + } + } + return sb.toString(); + } + public void close() throws IOException { - replacementReader.close(); + originalReader.close(); } } Added: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeSupport.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeSupport.java (rev 0) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeSupport.java 2007-03-28 16:19:23 UTC (rev 161) @@ -0,0 +1,74 @@ +/* +****************************************************************** +Copyright (c) 2001, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + +package org.custommonkey.xmlunit; + +/** + * Contains some common code for DoctypeReader and DoctypeInputStream. + * + * <p>When used with DoctypeInputStream it assumes that the whole + * DOCTYPE declaration consists of US-ASCII characters.</p> + */ +final class DoctypeSupport implements DoctypeConstants { + + private final String decl; + private int offset = 0; + + /** + * Encapsulates a DOCTYPE declaration for the given name and system id. + */ + DoctypeSupport(String name, String systemId) { + StringBuffer sb = new StringBuffer(DOCTYPE_OPEN_DECL); + sb.append(DOCTYPE).append(name).append(SYSTEM) + .append(systemId).append("\"").append(DOCTYPE_CLOSE_DECL); + decl = sb.toString(); + } + + /** + * Whether anybody has started to read the declaration. + */ + boolean hasBeenRead() { + return offset != 0; + } + + /** + * Reads the next character from the declaration. + * @return -1 if the end of the declaration has been reached. + */ + int read() { + return offset >= decl.length() ? -1 : decl.charAt(offset++); + } +} \ No newline at end of file Property changes on: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeSupport.java ___________________________________________________________________ Name: svn:executable + * Name: svn:eol-style + native Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java 2007-03-28 04:10:28 UTC (rev 160) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java 2007-03-28 16:19:23 UTC (rev 161) @@ -251,14 +251,15 @@ */ public Validator(InputSource sourceForValidation, String systemID, String doctype) - throws SAXException, IOException, ConfigurationException { + throws SAXException, ConfigurationException { this(sourceForValidation.getCharacterStream() != null - ? new DoctypeReader(sourceForValidation.getCharacterStream(), - doctype, systemID) - : new DoctypeReader(sourceForValidation.getByteStream(), - sourceForValidation.getEncoding(), - doctype, systemID), - systemID); + ? new InputSource(new DoctypeReader(sourceForValidation + .getCharacterStream(), + doctype, systemID)) + : new InputSource(new DoctypeInputStream(sourceForValidation + .getByteStream(), + doctype, systemID)), + systemID, true); } /** @@ -380,8 +381,8 @@ isValid = Boolean.TRUE; } else if (usingDoctypeReader) { try { - messages.append("\nContent was: ").append(((DoctypeReader) - validationInputSource.getCharacterStream()).getContent()); + messages.append("\nContent was: ") + .append(readFully(validationInputSource)); } catch (IOException e) { // silent but deadly? } @@ -490,4 +491,31 @@ parser.setProperty(JAXPConstants.Properties.SCHEMA_SOURCE, schemaSource); } + + private static String readFully(InputSource s) throws IOException { + return s.getCharacterStream() != null + ? readFully(s.getCharacterStream()) : readFully(s.getByteStream()); + } + + private static String readFully(Reader r) throws IOException { + StringBuffer sb = new StringBuffer(); + char[] buffer = new char[4096]; + int charsRead = -1; + while ((charsRead = r.read(buffer)) > -1) { + sb.append(buffer, 0, charsRead); + } + return sb.toString(); + } + + private static String readFully(java.io.InputStream is) throws IOException { + java.io.ByteArrayOutputStream baos = + new java.io.ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int bytesRead = -1; + while ((bytesRead = is.read(buffer)) > -1) { + baos.write(buffer, 0, bytesRead); + } + return new String(baos.toByteArray()); + } + } Added: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DoctypeInputStream.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DoctypeInputStream.java (rev 0) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DoctypeInputStream.java 2007-03-28 16:19:23 UTC (rev 161) @@ -0,0 +1,142 @@ +/* +****************************************************************** +Copyright (c) 200, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + +package org.custommonkey.xmlunit; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * JUnit test for DoctypeInputStream + */ +public class test_DoctypeInputStream extends TestCase { + + private static final String NEWLINE = System.getProperty("line.separator"); + private static final String NO_DTD = "<document><element>one</element></document>"; + private File testFile; + + public void tearDown() { + if (testFile != null) { + testFile.delete(); + } + } + + private FileInputStream testDocument(String content) + throws IOException { + testFile = File.createTempFile("xmlunit_", ".xml"); + FileOutputStream fos = new FileOutputStream(testFile); + OutputStreamWriter w = new OutputStreamWriter(fos, "ISO-8859-1"); + w.write(content); + w.close(); + + return new FileInputStream(testFile); + } + + private static String readFully(DoctypeInputStream dis) + throws IOException { + StringBuffer buf = new StringBuffer(); + char[] ch = new char[1024]; + int numChars; + InputStreamReader reader = + new InputStreamReader(dis, "ISO-8859-1"); + while ((numChars = reader.read(ch))!=-1) { + buf.append(ch, 0, numChars); + } + return buf.toString(); + } + + private void assertEquals(String expected, String input, String docType, + String systemId) throws IOException { + FileInputStream fis = null; + try { + fis = testDocument(input); + DoctypeInputStream doctypeInputStream = + new DoctypeInputStream(fis, docType, systemId); + + assertEquals(expected, readFully(doctypeInputStream)); + } finally { + if (fis != null) { + fis.close(); + } + } + } + + public void testRead() throws IOException { + String oz = "Chirurgische Verbesserungen sind g\u00fcnstig"; + assertEquals("<!DOCTYPE Kylie SYSTEM \"bumJob\">" + oz, + oz, "Kylie", "bumJob"); + } + + public void testReplaceDoctypeInternalDTD() throws IOException { + assertEquals("<!DOCTYPE ni SYSTEM \"shrubbery\">", + test_Constants.CHUCK_JONES_RIP_DTD_DECL, "ni", + "shrubbery"); + } + + public void XtestReplaceDoctypeExternalDTD() throws IOException { + assertEquals("<!DOCTYPE ni SYSTEM \"shrubbery\">", + "<! DOCTYPE PUBLIC \"yak\" SYSTEM \"llama\">", "ni", + "shrubbery"); + } + + public void testReplaceDoctypeNoDTD() throws IOException { + assertEquals("<!DOCTYPE ni SYSTEM \"shrubbery\">" + NO_DTD, + NO_DTD, "ni", "shrubbery"); + } + + public void testReplaceDoctypeNoDTDButXMLDecl() throws IOException { + assertEquals(test_Constants.XML_DECLARATION + + "<!DOCTYPE ni SYSTEM \"shrubbery\">" + NO_DTD, + test_Constants.XML_DECLARATION + NO_DTD, + "ni", "shrubbery"); + } + + public test_DoctypeInputStream(String name) { + super(name); + } + + public static TestSuite suite() { + return new TestSuite(test_DoctypeInputStream.class); + } +} + Property changes on: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DoctypeInputStream.java ___________________________________________________________________ Name: svn:executable + * Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-28 04:10:27
|
Revision: 160 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=160&view=rev Author: bodewig Date: 2007-03-27 21:10:28 -0700 (Tue, 27 Mar 2007) Log Message: ----------- Add information on URIResolver and InputSource Modified Paths: -------------- trunk/xmlunit/src/site/XMLUnit-Java.xml Modified: trunk/xmlunit/src/site/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-28 04:07:35 UTC (rev 159) +++ trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-28 04:10:28 UTC (rev 160) @@ -752,6 +752,10 @@ of XMLUnit's machinery. Examples can be found in <xref linkend="transform-intro"/>.</para> + <para>It is possible to provide a custom + <literal>javax.xml.transform.URIResolver</literal> via the + <literal>XMLUnit.setURIResolver</literal> method.</para> + <para>You can access the underlying XSLT transformer via <literal>XMLUnit.getTransformerFactory</literal>.</para> </section> @@ -872,8 +876,11 @@ <literal>XMLUnit.getControlDocumentBuilderFactory</literal>, <literal>XMLUnit.getTestDocumentBuilderFactory</literal> and <literal>XMLUnit.getSAXParserFactory</literal> (used by - Validator). The various <literal>build...</literal> methods - in <literal>XMLUnit</literal> provide convenience layers for + Validator). Not that all these methods return factories or + parsers that are namespace aware.</para> + + <para>The various <literal>build...</literal> methods in + <literal>XMLUnit</literal> provide convenience layers for building DOM <literal>Document</literal>s using the configured parsers.</para> @@ -907,6 +914,15 @@ <para>Using <literal>XMLUnit.setIgnoreWhitespace</literal> it is possible to make the test and control parser ignore this kind of whitespace.</para> + + <para>Note that setting this property to + <literal>true</literal> usually doesn't have any effect since + it only works on validating parsers and XMLUnit doesn't enable + validation by default. It does have an effect when comparing + pieces of XML, though, since the same flag is used for a + different purpose as well in that case. See <xref + linkend="comparing-config"/> for more details.</para> + </section> </section> @@ -927,12 +943,27 @@ <literal>Transform</literal> class.</para> </listitem> + <listitem>A SAX <literal>InputSource</literal>. + + <para>This is the most generic way since + <literal>InputSource</literal> allows you to read from + arbitrary <literal>InputStream</literal>s or + <literal>Reader</literal>s. Use an + <literal>InputStream</literal> wrapped into an + <literal>InputSource</literal> if you want the XML parser to + pick the proper encoding from the XML declaration.</para> + </listitem> + <listitem>A <literal>String</literal>. <para>Here a DOM <literal>Document</literal> is built from the input <literal>String</literal> using the JAXP parser specified for control or test documents - depending on whether the input is a control or test piece of XML.</para> + + <para>Note that using a <literal>String</literal> assumes + that you XML has already been converted from its XML + encoding to a Java <literal>String</literal> upfront.</para> </listitem> <listitem>A <literal>Reader</literal>. @@ -1110,6 +1141,14 @@ </itemizedlist> </listitem> + <listitem>It is now possible to provide a custom + <literal>javax.xml.transform.URIResolver</literal> for + transformations.</listitem> + + <listitem>New overloads have been added that allow + <literal>org.xml.sax.InputSource</literal> to be used as a + "piece of XML" in many classes.</listitem> + <listitem> <para>A new package <literal>org.custommonkey.xmlunit.examples</literal> has This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-28 04:07:35
|
Revision: 159 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=159&view=rev Author: bodewig Date: 2007-03-27 21:07:35 -0700 (Tue, 27 Mar 2007) Log Message: ----------- More overrides that allow InputSource as source Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLAssert.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Validator.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java 2007-03-28 04:06:22 UTC (rev 158) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java 2007-03-28 04:07:35 UTC (rev 159) @@ -38,6 +38,8 @@ import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; @@ -79,6 +81,32 @@ } /** + * Create a Reader whose XML content is provided by the originalSource with + * the exception of the DOCTYPE which is provided by the doctypeName + * and systemID. + * @param originalSource + * @param doctypeName + * @param systemID + */ + public DoctypeReader(InputStream originalSource, String encoding, + String doctypeName, String systemID) + throws IOException { + this(encoding != null + ? new InputStreamReader(originalSource, encoding) + : xmlStreamToReader(originalSource), + doctypeName, systemID); + } + + // XXX - we are cheating here, we should read into the source + // stream to see whether the XML decl (if any) specifies the + // encoding and then return an InputStreamReader using the proper + // encoding + private static Reader xmlStreamToReader(InputStream originalSource) + throws IOException { + return new InputStreamReader(originalSource); + } + + /** * @return the content of the original source, without amendments or * substitutions. Safe to call multiple times. * @throws IOException if thrown while reading from the original source Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java 2007-03-28 04:06:22 UTC (rev 158) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java 2007-03-28 04:07:35 UTC (rev 159) @@ -240,6 +240,29 @@ /** * Full constructor. + * Validates the contents of the InputSource using the DTD + * specified with the systemID and named with the doctype name. + * + * @param sourceForValidation + * @param systemID + * @param doctype + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + */ + public Validator(InputSource sourceForValidation, String systemID, + String doctype) + throws SAXException, IOException, ConfigurationException { + this(sourceForValidation.getCharacterStream() != null + ? new DoctypeReader(sourceForValidation.getCharacterStream(), + doctype, systemID) + : new DoctypeReader(sourceForValidation.getByteStream(), + sourceForValidation.getEncoding(), + doctype, systemID), + systemID); + } + + /** + * Full constructor. * Validates the contents of the Reader using the DTD specified with the * systemID and named with the doctype name. * @@ -249,9 +272,12 @@ * @throws SAXException * @throws ConfigurationException if validation could not be turned on */ - public Validator(Reader readerForValidation, String systemID, String doctype) + public Validator(Reader readerForValidation, String systemID, + String doctype) throws SAXException, ConfigurationException { - this(new DoctypeReader(readerForValidation, doctype, systemID), + this(readerForValidation instanceof DoctypeReader + ? readerForValidation + : new DoctypeReader(readerForValidation, doctype, systemID), systemID); } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLAssert.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLAssert.java 2007-03-28 04:06:22 UTC (rev 158) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLAssert.java 2007-03-28 04:07:35 UTC (rev 159) @@ -49,6 +49,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -109,9 +110,7 @@ * @param assertion true if asserting that result is similar */ public static void assertXMLEqual(Diff diff, boolean assertion) { - if (assertion != diff.similar()) { - fail(diff.toString()); - } + assertXMLEqual(null, diff, assertion); } /** @@ -120,21 +119,28 @@ * @param diff the result of an XML comparison * @param assertion true if asserting that result is similar */ - public static void assertXMLEqual(String msg, Diff diff, boolean assertion) { + public static void assertXMLEqual(String msg, Diff diff, + boolean assertion) { if (assertion != diff.similar()) { - fail(msg + ", " + diff.toString()); + fail(getFailMessage(msg, diff)); } } + private static String getFailMessage(String msg, Diff diff) { + StringBuffer sb = new StringBuffer(); + if (msg != null && msg.length() > 0) { + sb.append(msg).append(", "); + } + return sb.append(diff.toString()).toString(); + } + /** * Assert that the result of an XML comparison is or is not identical * @param diff the result of an XML comparison * @param assertion true if asserting that result is identical */ public static void assertXMLIdentical(Diff diff, boolean assertion) { - if (assertion != diff.identical()) { - fail(diff.toString()); - } + assertXMLIdentical(null, diff, assertion); } /** @@ -156,7 +162,7 @@ */ public static void assertXMLIdentical(String msg, Diff diff, boolean assertion) { if (assertion != diff.identical()) { - fail(msg + ", " + diff.toString()); + fail(getFailMessage(msg, diff)); } } @@ -167,10 +173,21 @@ * @throws SAXException * @throws IOException */ + public static void assertXMLEqual(InputSource control, InputSource test) + throws SAXException, IOException { + assertXMLEqual(null, control, test); + } + + /** + * Assert that two XML documents are similar + * @param control XML to be compared against + * @param test XML to be tested + * @throws SAXException + * @throws IOException + */ public static void assertXMLEqual(String control, String test) throws SAXException, IOException { - Diff diff = new Diff(control, test); - assertXMLEqual(diff, true); + assertXMLEqual(null, control, test); } /** @@ -179,8 +196,7 @@ * @param test XML to be tested */ public static void assertXMLEqual(Document control, Document test) { - Diff diff = new Diff(control, test); - assertXMLEqual(diff, true); + assertXMLEqual(null, control, test); } /** @@ -192,8 +208,22 @@ */ public static void assertXMLEqual(Reader control, Reader test) throws SAXException, IOException { + assertXMLEqual(null, control, test); + } + + /** + * Assert that two XML documents are similar + * @param err Message to be displayed on assertion failure + * @param control XML to be compared against + * @param test XML to be tested + * @throws SAXException + * @throws IOException + */ + public static void assertXMLEqual(String err, InputSource control, + InputSource test) + throws SAXException, IOException { Diff diff = new Diff(control, test); - assertXMLEqual(diff, true); + assertXMLEqual(err, diff, true); } /** @@ -243,24 +273,21 @@ * @throws SAXException * @throws IOException */ - public static void assertXMLNotEqual(String control, String test) + public static void assertXMLNotEqual(InputSource control, InputSource test) throws SAXException, IOException { - Diff diff = new Diff(control, test); - assertXMLEqual(diff, false); + assertXMLNotEqual(null, control, test); } /** * Assert that two XML documents are NOT similar - * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested * @throws SAXException * @throws IOException */ - public static void assertXMLNotEqual(String err, String control, String test) + public static void assertXMLNotEqual(String control, String test) throws SAXException, IOException { - Diff diff = new Diff(control, test); - assertXMLEqual(err, diff, false); + assertXMLNotEqual(null, control, test); } /** @@ -269,33 +296,48 @@ * @param test XML to be tested */ public static void assertXMLNotEqual(Document control, Document test) { - Diff diff = new Diff(control, test); - assertXMLEqual(diff, false); + assertXMLNotEqual(null, control, test); } /** * Assert that two XML documents are NOT similar + * @param control XML to be compared against + * @param test XML to be tested + * @throws SAXException + * @throws IOException + */ + public static void assertXMLNotEqual(Reader control, Reader test) + throws SAXException, IOException { + assertXMLNotEqual(null, control, test); + } + + /** + * Assert that two XML documents are NOT similar * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested + * @throws SAXException + * @throws IOException */ - public static void assertXMLNotEqual(String err, Document control, - Document test) { + public static void assertXMLNotEqual(String err, InputSource control, + InputSource test) + throws SAXException, IOException { Diff diff = new Diff(control, test); assertXMLEqual(err, diff, false); } /** * Assert that two XML documents are NOT similar + * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested * @throws SAXException * @throws IOException */ - public static void assertXMLNotEqual(Reader control, Reader test) + public static void assertXMLNotEqual(String err, String control, String test) throws SAXException, IOException { Diff diff = new Diff(control, test); - assertXMLEqual(diff, false); + assertXMLEqual(err, diff, false); } /** @@ -303,6 +345,18 @@ * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested + */ + public static void assertXMLNotEqual(String err, Document control, + Document test) { + Diff diff = new Diff(control, test); + assertXMLEqual(err, diff, false); + } + + /** + * Assert that two XML documents are NOT similar + * @param err Message to be displayed on assertion failure + * @param control XML to be compared against + * @param test XML to be tested * @throws SAXException * @throws IOException */ @@ -326,6 +380,20 @@ } /** + * Assert that the node lists of two Xpaths in the same document are equal + * @param xpathOne + * @param xpathTwo + * @param document + * @see XpathEngine + */ + public static void assertXpathsEqual(String controlXpath, String testXpath, + InputSource document) + throws SAXException, IOException, XpathException { + assertXpathsEqual(controlXpath, testXpath, + XMLUnit.buildControlDocument(document)); + } + + /** * Assert that the node lists of two Xpaths in the same XML string are * equal * @param xpathOne @@ -342,6 +410,25 @@ } /** + * Assert that the node lists of two Xpaths in two documents are equal + * @param xpathOne + * @param xpathTwo + * @param controlDocument + * @param testDocument + * @see XpathEngine + */ + public static void assertXpathsEqual(String controlXpath, + InputSource controlDocument, + String testXpath, + InputSource testDocument) + throws SAXException, IOException, XpathException { + assertXpathsEqual(controlXpath, + XMLUnit.buildControlDocument(controlDocument), + testXpath, + XMLUnit.buildTestDocument(testDocument)); + } + + /** * Assert that the node lists of two Xpaths in two XML strings are equal * @param xpathOne * @param inControlXMLString @@ -365,7 +452,8 @@ * Assert that the node lists of two Xpaths in two documents are equal * @param xpathOne * @param xpathTwo - * @param document + * @param controlDocument + * @param testDocument * @see XpathEngine */ public static void assertXpathsEqual(String controlXpath, @@ -398,6 +486,21 @@ } /** + * Assert that the node lists of two Xpaths in the same document are NOT equal + * @param xpathOne + * @param xpathTwo + * @param document + * @see XpathEngine + */ + public static void assertXpathsNotEqual(String controlXpath, + String testXpath, + InputSource document) + throws SAXException, IOException, XpathException { + assertXpathsNotEqual(controlXpath, testXpath, + XMLUnit.buildControlDocument(document)); + } + + /** * Assert that the node lists of two Xpaths in the same XML string are NOT * equal * @param xpathOne @@ -435,6 +538,27 @@ } /** + * Assert that the node lists of two Xpaths in two XML strings are + * NOT equal + * @param xpathOne + * @param controlDocument + * @param xpathTwo + * @param testDocument + * @throws SAXException + * @throws IOException + */ + public static void assertXpathsNotEqual(String controlXpath, + InputSource controlDocument, + String testXpath, + InputSource testDocument) + throws SAXException, IOException, XpathException { + assertXpathsNotEqual(controlXpath, + XMLUnit.buildControlDocument(controlDocument), + testXpath, + XMLUnit.buildTestDocument(testDocument)); + } + + /** * Assert that the node lists of two Xpaths in two documents are NOT equal * @param xpathOne * @param xpathTwo @@ -475,6 +599,23 @@ * equal * @param xpathOne * @param xpathTwo + * @param document + * @throws SAXException + * @throws IOException + */ + public static void assertXpathValuesEqual(String controlXpath, + String testXpath, + InputSource document) + throws SAXException, IOException, XpathException { + assertXpathValuesEqual(controlXpath, testXpath, + XMLUnit.buildControlDocument(document)); + } + + /** + * Assert that the evaluation of two Xpaths in the same XML string are + * equal + * @param xpathOne + * @param xpathTwo * @param inXMLString * @throws SAXException * @throws IOException @@ -491,6 +632,26 @@ /** * Assert that the evaluation of two Xpaths in two XML strings are equal * @param xpathOne + * @param control + * @param xpathTwo + * @param test + * @throws SAXException + * @throws IOException + */ + public static void assertXpathValuesEqual(String controlXpath, + InputSource control, + String testXpath, + InputSource test) + throws SAXException, IOException, XpathException { + assertXpathValuesEqual(controlXpath, + XMLUnit.buildControlDocument(control), + testXpath, + XMLUnit.buildTestDocument(test)); + } + + /** + * Assert that the evaluation of two Xpaths in two XML strings are equal + * @param xpathOne * @param inControlXMLString * @param xpathTwo * @param inTestXMLString @@ -531,6 +692,23 @@ * NOT equal * @param xpathOne * @param xpathTwo + * @param control + * @throws SAXException + * @throws IOException + */ + public static void assertXpathValuesNotEqual(String controlXpath, + String testXpath, + InputSource control) + throws SAXException, IOException, XpathException { + assertXpathValuesNotEqual(controlXpath, testXpath, + XMLUnit.buildControlDocument(control)); + } + + /** + * Assert that the evaluation of two Xpaths in the same XML string are + * NOT equal + * @param xpathOne + * @param xpathTwo * @param inXMLString * @throws SAXException * @throws IOException @@ -562,10 +740,30 @@ * Assert that the evaluation of two Xpaths in two XML strings are * NOT equal * @param xpathOne + * @param control + * @param xpathTwo + * @param test + * @throws SAXException + * @throws IOException + */ + public static void assertXpathValuesNotEqual(String controlXpath, + InputSource control, + String testXpath, + InputSource test) + throws SAXException, IOException, XpathException { + assertXpathValuesNotEqual(controlXpath, + XMLUnit.buildControlDocument(control), + testXpath, + XMLUnit.buildTestDocument(test)); + } + + /** + * Assert that the evaluation of two Xpaths in two XML strings are + * NOT equal + * @param xpathOne * @param inControlXMLString * @param xpathTwo * @param inTestXMLString - * @param ctx * @throws SAXException * @throws IOException */ @@ -608,6 +806,24 @@ } /** + * Assert the value of an Xpath expression in an XML document. + * @param expectedValue + * @param xpathExpression + * @param control + * @throws SAXException + * @throws IOException + * @see XpathEngine which provides the underlying evaluation mechanism + */ + public static void assertXpathEvaluatesTo(String expectedValue, + String xpathExpression, + InputSource control) + throws SAXException, IOException, + XpathException { + Document document = XMLUnit.buildControlDocument(control); + assertXpathEvaluatesTo(expectedValue, xpathExpression, document); + } + + /** * Assert the value of an Xpath expression in an XML String * @param expectedValue * @param xpathExpression @@ -644,6 +860,19 @@ /** * Assert that a specific XPath exists in some given XML * @param inXpathExpression + * @param control + * @see XpathEngine which provides the underlying evaluation mechanism + */ + public static void assertXpathExists(String xPathExpression, + InputSource control) + throws IOException, SAXException, XpathException { + Document inDocument = XMLUnit.buildControlDocument(control); + assertXpathExists(xPathExpression, inDocument); + } + + /** + * Assert that a specific XPath exists in some given XML + * @param inXpathExpression * @param inXMLString * @see XpathEngine which provides the underlying evaluation mechanism */ @@ -674,6 +903,19 @@ /** * Assert that a specific XPath does NOT exist in some given XML * @param inXpathExpression + * @param control + * @see XpathEngine which provides the underlying evaluation mechanism + */ + public static void assertXpathNotExists(String xPathExpression, + InputSource control) + throws IOException, SAXException, XpathException { + Document inDocument = XMLUnit.buildControlDocument(control); + assertXpathNotExists(xPathExpression, inDocument); + } + + /** + * Assert that a specific XPath does NOT exist in some given XML + * @param inXpathExpression * @param inXMLString * @see XpathEngine which provides the underlying evaluation mechanism */ @@ -702,6 +944,19 @@ } /** + * Assert that an InputSource containing XML contains valid XML: + * the document must contain a DOCTYPE declaration to be validated + * @param xml + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + * @see Validator + */ + public static void assertXMLValid(InputSource xml) + throws SAXException, ConfigurationException { + assertXMLValid(new Validator(xml)); + } + + /** * Assert that a String containing XML contains valid XML: the String must * contain a DOCTYPE declaration to be validated * @param xmlString @@ -711,10 +966,25 @@ */ public static void assertXMLValid(String xmlString) throws SAXException, ConfigurationException { - assertXMLValid(new Validator(new StringReader(xmlString))); + assertXMLValid(new Validator(xmlString)); } /** + * Assert that an InputSource containing XML contains valid XML: + * the document must contain a DOCTYPE to be validated, but the + * validation will use the systemId to obtain the DTD + * @param xml + * @param systemId + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + * @see Validator + */ + public static void assertXMLValid(InputSource xml, String systemId) + throws SAXException, ConfigurationException { + assertXMLValid(new Validator(xml, systemId)); + } + + /** * Assert that a String containing XML contains valid XML: the String must * contain a DOCTYPE to be validated, but the validation will use the * systemId to obtain the DTD @@ -726,10 +996,28 @@ */ public static void assertXMLValid(String xmlString, String systemId) throws SAXException, ConfigurationException { - assertXMLValid(new Validator(new StringReader(xmlString), systemId)); + assertXMLValid(new Validator(xmlString, systemId)); } /** + * Assert that a piece of XML contains valid XML: the document + * will be given a DOCTYPE to be validated with the name and + * systemId specified regardless of whether it already contains a + * doctype declaration. + * @param xml + * @param systemId + * @param doctype + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + * @see Validator + */ + public static void assertXMLValid(InputSource xml, String systemId, + String doctype) + throws SAXException, ConfigurationException { + assertXMLValid(new Validator(xml, systemId, doctype)); + } + + /** * Assert that a String containing XML contains valid XML: the String will * be given a DOCTYPE to be validated with the name and systemId specified * regardless of whether it already contains a doctype declaration. @@ -756,6 +1044,25 @@ /** * Execute a <code>NodeTest<code> for a single node type * and assert that it passes + * @param xml XML to be tested + * @param tester The test strategy + * @param nodeType The node type to be tested: constants defined + * in {@link Node org.w3c.dom.Node} e.g. <code>Node.ELEMENT_NODE</code> + * @throws SAXException + * @throws IOException + * @see AbstractNodeTester + * @see CountingNodeTester + */ + public static void assertNodeTestPasses(InputSource xml, NodeTester tester, + short nodeType) + throws SAXException, IOException { + NodeTest test = new NodeTest(xml); + assertNodeTestPasses(test, tester, new short[] {nodeType}, true); + } + + /** + * Execute a <code>NodeTest<code> for a single node type + * and assert that it passes * @param xmlString XML to be tested * @param tester The test strategy * @param nodeType The node type to be tested: constants defined Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java 2007-03-28 04:06:22 UTC (rev 158) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java 2007-03-28 04:07:35 UTC (rev 159) @@ -45,6 +45,7 @@ import junit.framework.TestCase; import org.w3c.dom.Document; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -105,6 +106,19 @@ } /** + * Compare XML documents provided by two InputSource classes + * @param control Control document + * @param test Document to test + * @return Diff object describing differences in documents + * @throws SAXException + * @throws IOException + */ + public Diff compareXML(InputSource control, InputSource test) + throws SAXException, IOException { + return XMLUnit.compareXML(control, test); + } + + /** * Compare XML documents provided by two Reader classes * @param control Control document * @param test Document to test @@ -233,6 +247,18 @@ * @throws SAXException * @throws IOException */ + public void assertXMLEqual(InputSource control, InputSource test) + throws SAXException, IOException { + XMLAssert.assertXMLEqual(control, test); + } + + /** + * Assert that two XML documents are similar + * @param control XML to be compared against + * @param test XML to be tested + * @throws SAXException + * @throws IOException + */ public void assertXMLEqual(String control, String test) throws SAXException, IOException { XMLAssert.assertXMLEqual(control, test); @@ -277,7 +303,21 @@ * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested + * @throws SAXException + * @throws IOException */ + public void assertXMLEqual(String err, InputSource control, + InputSource test) + throws SAXException, IOException { + XMLAssert.assertXMLEqual(err, control, test); + } + + /** + * Assert that two XML documents are similar + * @param err Message to be displayed on assertion failure + * @param control XML to be compared against + * @param test XML to be tested + */ public void assertXMLEqual(String err, Document control, Document test) { XMLAssert.assertXMLEqual(err, control, test); } @@ -302,22 +342,21 @@ * @throws SAXException * @throws IOException */ - public void assertXMLNotEqual(String control, String test) + public void assertXMLNotEqual(InputSource control, InputSource test) throws SAXException, IOException { XMLAssert.assertXMLNotEqual(control, test); } /** * Assert that two XML documents are NOT similar - * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested * @throws SAXException * @throws IOException */ - public void assertXMLNotEqual(String err, String control, String test) + public void assertXMLNotEqual(String control, String test) throws SAXException, IOException { - XMLAssert.assertXMLNotEqual(err, control, test); + XMLAssert.assertXMLNotEqual(control, test); } /** @@ -331,24 +370,41 @@ /** * Assert that two XML documents are NOT similar + * @param control XML to be compared against + * @param test XML to be tested + * @throws SAXException + * @throws IOException + */ + public void assertXMLNotEqual(Reader control, Reader test) + throws SAXException, IOException { + XMLAssert.assertXMLNotEqual(control, test); + } + + /** + * Assert that two XML documents are NOT similar * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested + * @throws SAXException + * @throws IOException */ - public void assertXMLNotEqual(String err, Document control, Document test) { + public void assertXMLNotEqual(String err, InputSource control, + InputSource test) + throws SAXException, IOException { XMLAssert.assertXMLNotEqual(err, control, test); } /** * Assert that two XML documents are NOT similar + * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested * @throws SAXException * @throws IOException */ - public void assertXMLNotEqual(Reader control, Reader test) + public void assertXMLNotEqual(String err, String control, String test) throws SAXException, IOException { - XMLAssert.assertXMLNotEqual(control, test); + XMLAssert.assertXMLNotEqual(err, control, test); } /** @@ -356,6 +412,16 @@ * @param err Message to be displayed on assertion failure * @param control XML to be compared against * @param test XML to be tested + */ + public void assertXMLNotEqual(String err, Document control, Document test) { + XMLAssert.assertXMLNotEqual(err, control, test); + } + + /** + * Assert that two XML documents are NOT similar + * @param err Message to be displayed on assertion failure + * @param control XML to be compared against + * @param test XML to be tested * @throws SAXException * @throws IOException */ @@ -372,6 +438,19 @@ * @see XpathEngine */ public void assertXpathsEqual(String controlXpath, String testXpath, + InputSource document) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathsEqual(controlXpath, testXpath, document); + } + + /** + * Assert that the node lists of two Xpaths in the same document are equal + * @param xpathOne + * @param xpathTwo + * @param document + * @see XpathEngine + */ + public void assertXpathsEqual(String controlXpath, String testXpath, Document document) throws XpathException { XMLAssert.assertXpathsEqual(controlXpath, testXpath, document); @@ -393,6 +472,22 @@ } /** + * Assert that the node lists of two Xpaths in two XML pieces are equal + * @param xpathOne + * @param control + * @param xpathTwo + * @param test + * @throws SAXException + * @throws IOException + */ + public void assertXpathsEqual(String controlXpath, InputSource control, + String testXpath, InputSource test) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathsEqual(controlXpath, control, + testXpath, test); + } + + /** * Assert that the node lists of two Xpaths in two XML strings are equal * @param xpathOne * @param inControlXMLString @@ -439,6 +534,21 @@ } /** + * Assert that the node lists of two Xpaths in the same XML are NOT + * equal + * @param xpathOne + * @param xpathTwo + * @param control + * @throws SAXException + * @throws IOException + */ + public void assertXpathsNotEqual(String controlXpath, String testXpath, + InputSource control) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathsNotEqual(controlXpath, testXpath, control); + } + + /** * Assert that the node lists of two Xpaths in the same XML string are NOT * equal * @param xpathOne @@ -455,6 +565,22 @@ } /** + * Assert that the node lists of two Xpaths in two pieces of XML + * are NOT equal + * @param xpathOne + * @param control + * @param xpathTwo + * @param test + * @throws SAXException + * @throws IOException + */ + public void assertXpathsNotEqual(String controlXpath, InputSource control, + String testXpath, InputSource test) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathsNotEqual(controlXpath, control, testXpath, test); + } + + /** * Assert that the node lists of two Xpaths in two XML strings are NOT equal * @param xpathOne * @param inControlXMLString @@ -501,6 +627,21 @@ } /** + * Assert that the evaluation of two Xpaths in the same XML are + * equal + * @param xpathOne + * @param xpathTwo + * @param control + * @throws SAXException + * @throws IOException + */ + public void assertXpathValuesEqual(String controlXpath, String testXpath, + InputSource control) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathValuesEqual(controlXpath, testXpath, control); + } + + /** * Assert that the evaluation of two Xpaths in the same XML string are * equal * @param xpathOne @@ -519,6 +660,24 @@ /** * Assert that the evaluation of two Xpaths in two XML strings are equal * @param xpathOne + * @param control + * @param xpathTwo + * @param test + * @throws SAXException + * @throws IOException + */ + public void assertXpathValuesEqual(String controlXpath, + InputSource control, + String testXpath, + InputSource test) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathValuesEqual(controlXpath, control, + testXpath, test); + } + + /** + * Assert that the evaluation of two Xpaths in two XML strings are equal + * @param xpathOne * @param inControlXMLString * @param xpathTwo * @param inTestXMLString @@ -555,6 +714,23 @@ * NOT equal * @param xpathOne * @param xpathTwo + * @param control + * @throws SAXException + * @throws IOException + */ + public void assertXpathValuesNotEqual(String controlXpath, + String testXpath, + InputSource control) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathValuesNotEqual(controlXpath, testXpath, + control); + } + + /** + * Assert that the evaluation of two Xpaths in the same XML string are + * NOT equal + * @param xpathOne + * @param xpathTwo * @param inXMLString * @throws SAXException * @throws IOException @@ -584,6 +760,25 @@ * Assert that the evaluation of two Xpaths in two XML strings are * NOT equal * @param xpathOne + * @param control + * @param xpathTwo + * @param test + * @throws SAXException + * @throws IOException + */ + public void assertXpathValuesNotEqual(String controlXpath, + InputSource control, + String testXpath, + InputSource test) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathValuesNotEqual(controlXpath, control, + testXpath, test); + } + + /** + * Assert that the evaluation of two Xpaths in two XML strings are + * NOT equal + * @param xpathOne * @param inControlXMLString * @param xpathTwo * @param inTestXMLString @@ -620,6 +815,23 @@ * Assert the value of an Xpath expression in an XML String * @param expectedValue * @param xpathExpression + * @param control + * @throws SAXException + * @throws IOException + * @see XpathEngine which provides the underlying evaluation mechanism + */ + public void assertXpathEvaluatesTo(String expectedValue, + String xpathExpression, + InputSource control) + throws SAXException, IOException, XpathException { + XMLAssert.assertXpathEvaluatesTo(expectedValue, xpathExpression, + control); + } + + /** + * Assert the value of an Xpath expression in an XML String + * @param expectedValue + * @param xpathExpression * @param inXMLString * @throws SAXException * @throws IOException @@ -653,8 +865,19 @@ /** * Assert that a specific XPath exists in some given XML * @param inXpathExpression + * @param xml + * @see XpathEngine which provides the underlying evaluation mechanism + */ + public void assertXpathExists(String xPathExpression, + InputSource xml) + throws IOException, SAXException, XpathException { + XMLAssert.assertXpathExists(xPathExpression, xml); + } + + /** + * Assert that a specific XPath exists in some given XML + * @param inXpathExpression * @param inXMLString - * @param ctx * @see XpathEngine which provides the underlying evaluation mechanism */ public void assertXpathExists(String xPathExpression, @@ -678,6 +901,18 @@ /** * Assert that a specific XPath does NOT exist in some given XML * @param inXpathExpression + * @param xml + * @see XpathEngine which provides the underlying evaluation mechanism + */ + public void assertXpathNotExists(String xPathExpression, + InputSource xml) + throws IOException, SAXException, XpathException { + XMLAssert.assertXpathNotExists(xPathExpression, xml); + } + + /** + * Assert that a specific XPath does NOT exist in some given XML + * @param inXpathExpression * @param inXMLString * @see XpathEngine which provides the underlying evaluation mechanism */ @@ -724,6 +959,19 @@ } /** + * Assert that a piece of XML contains valid XML: the input must + * contain a DOCTYPE declaration to be validated + * @param xml + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + * @see Validator + */ + public void assertXMLValid(InputSource xml) + throws SAXException, ConfigurationException { + XMLAssert.assertXMLValid(xml); + } + + /** * Assert that a String containing XML contains valid XML: the String must * contain a DOCTYPE declaration to be validated * @param xmlString @@ -737,6 +985,21 @@ } /** + * Assert that a piece of XML contains valid XML: the document must + * contain a DOCTYPE to be validated, but the validation will use the + * systemId to obtain the DTD + * @param xml + * @param systemId + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + * @see Validator + */ + public void assertXMLValid(InputSource xml, String systemId) + throws SAXException, ConfigurationException { + XMLAssert.assertXMLValid(xml, systemId); + } + + /** * Assert that a String containing XML contains valid XML: the String must * contain a DOCTYPE to be validated, but the validation will use the * systemId to obtain the DTD @@ -752,6 +1015,24 @@ } /** + * Assert that a piece of XML contains valid XML: the document + * will be given a DOCTYPE to be validated with the name and + * systemId specified regardless of whether it already contains a + * doctype declaration. + * @param xml + * @param systemId + * @param doctype + * @throws SAXException + * @throws ConfigurationException if validation could not be turned on + * @see Validator + */ + public void assertXMLValid(InputSource xml, String systemId, + String doctype) + throws SAXException, ConfigurationException { + XMLAssert.assertXMLValid(xml, systemId, doctype); + } + + /** * Assert that a String containing XML contains valid XML: the String will * be given a DOCTYPE to be validated with the name and systemId specified * regardless of whether it already contains a doctype declaration. @@ -778,6 +1059,24 @@ /** * Execute a <code>NodeTest<code> for a single node type * and assert that it passes + * @param xml XML to be tested + * @param tester The test strategy + * @param nodeType The node type to be tested: constants defined + * in {@link Node org.w3c.dom.Node} e.g. <code>Node.ELEMENT_NODE</code> + * @throws SAXException + * @throws IOException + * @see AbstractNodeTester + * @see CountingNodeTester + */ + public void assertNodeTestPasses(InputSource xml, NodeTester tester, + short nodeType) + throws SAXException, IOException { + XMLAssert.assertNodeTestPasses(xml, tester, nodeType); + } + + /** + * Execute a <code>NodeTest<code> for a single node type + * and assert that it passes * @param xmlString XML to be tested * @param tester The test strategy * @param nodeType The node type to be tested: constants defined Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java 2007-03-28 04:06:22 UTC (rev 158) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java 2007-03-28 04:07:35 UTC (rev 159) @@ -507,6 +507,19 @@ return "1.1alpha"; } + /** + * Compare XML documents provided by two InputSource classes + * @param control Control document + * @param test Document to test + * @return Diff object describing differences in documents + * @throws SAXException + * @throws IOException + */ + public static Diff compareXML(InputSource control, InputSource test) + throws SAXException, IOException { + return new Diff(control, test); + } + /** * Compare XML documents provided by two Reader classes * @param control Control document Modified: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Validator.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Validator.java 2007-03-28 04:06:22 UTC (rev 158) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Validator.java 2007-03-28 04:07:35 UTC (rev 159) @@ -39,10 +39,13 @@ import junit.framework.AssertionFailedError; import junit.framework.TestSuite; import org.w3c.dom.Document; +import org.xml.sax.InputSource; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; +import java.io.StringBufferInputStream; import java.io.StringReader; /** @@ -56,15 +59,18 @@ public void testXSchema() throws Exception{ File xsdFile = new File(test_Constants.BASEDIR + "/tests/etc/Book.xsd"); - assertTrue("xsdFile " + xsdFile.getAbsolutePath() + " exists", xsdFile.exists()); + assertTrue("xsdFile " + xsdFile.getAbsolutePath() + " exists", + xsdFile.exists()); - File xmlFile = new File(test_Constants.BASEDIR + "/tests/etc/BookXsdGenerated.xml"); - assertTrue("xmlFile " + xmlFile.getAbsolutePath() + " exists", xmlFile.exists()); - validator = new Validator(new FileReader(xmlFile)); + File xmlFile = new File(test_Constants.BASEDIR + + "/tests/etc/BookXsdGenerated.xml"); + assertTrue("xmlFile " + xmlFile.getAbsolutePath() + " exists", + xmlFile.exists()); + validator = + new Validator(new InputSource(new FileInputStream(xmlFile))); validator.useXMLSchema(true); - - validator.assertIsValid(); + assertTrue("Schema " + validator.toString(), validator.isValid()); } public void testIsValidGood() throws Exception { @@ -72,8 +78,7 @@ + test_Constants.CHUCK_JONES_RIP_DTD_DECL + test_Constants.CHUCK_JONES_RIP_XML; validator = new Validator(new StringReader(toonXML)); - assertEquals("toonXML " + validator.toString(), - true, validator.isValid()); + assertTrue("toonXML " + validator.toString(), validator.isValid()); // test XMLTestCase passXMLTestCaseTest(toonXML); passXMLTestCaseTest(validator); @@ -90,7 +95,7 @@ public void testIsValidExternalSystemId() throws Exception { writeTempDTDFile(); - assertEquals(tempDTDFile.getAbsolutePath(), true, tempDTDFile.exists()); + assertTrue(tempDTDFile.getAbsolutePath(), tempDTDFile.exists()); String externalDTD = test_Constants.XML_DECLARATION + test_Constants.DOCUMENT_WITH_GOOD_EXTERNAL_DTD; @@ -98,8 +103,7 @@ validator = new Validator(new StringReader(externalDTD), tempDTDUrl); - assertEquals("externalDTD " + validator.toString(), - true, validator.isValid()); + assertTrue("externalDTD " + validator.toString(), validator.isValid()); // test XMLTestCase passXMLTestCaseTest(externalDTD, tempDTDFile.toURL().toExternalForm()); passXMLTestCaseTest(validator); @@ -109,8 +113,7 @@ validator = new Validator(new StringReader(noDTD), tempDTDFile.toURL().toExternalForm()); - assertEquals("noDTD " + validator.toString(), - false, validator.isValid()); + assertFalse("noDTD " + validator.toString(), validator.isValid()); // test XMLTestCase failXMLTestCaseTest(noDTD, tempDTDFile.toURL().toExternalForm()); failXMLTestCaseTest(validator); @@ -118,7 +121,7 @@ public void testIsValidNoDTD() throws Exception { writeTempDTDFile(); - assertEquals(tempDTDFile.getAbsolutePath(), true, tempDTDFile.exists()); + assertTrue(tempDTDFile.getAbsolutePath(), tempDTDFile.exists()); String noDTD = test_Constants.CHUCK_JONES_RIP_XML; String systemid = tempDTDFile.toURL().toExternalForm(); @@ -126,39 +129,33 @@ String notDoctype = "anima"; validator = new Validator(new StringReader(noDTD), systemid, doctype); - assertEquals(validator.toString(), true, validator.isValid()); + assertTrue(validator.toString(), validator.isValid()); // test XMLTestCase passXMLTestCaseTest(noDTD, systemid, doctype); passXMLTestCaseTest(validator); + // and Document constructor + Document document = getDocument(noDTD); + validator = new Validator(document, systemid, doctype); + assertTrue("Document " + validator.toString(), validator.isValid()); validator = new Validator(new StringReader(noDTD), systemid, notDoctype); - assertEquals(validator.toString(), false, validator.isValid()); + assertFalse(validator.toString(), validator.isValid()); // test XMLTestCase failXMLTestCaseTest(noDTD, systemid, notDoctype); failXMLTestCaseTest(validator); - - Document document = getDocument(noDTD); - validator = new Validator(document, systemid, doctype); - assertEquals("Document " + validator.toString(), - true, validator.isValid()); - // test XMLTestCase - passXMLTestCaseTest(validator); - + // and Document constructor validator = new Validator(document, systemid, notDoctype); - assertEquals("Document " + validator.toString(), - false, validator.isValid()); - // test XMLTestCase - failXMLTestCaseTest(validator); + assertFalse("Document " + validator.toString(), validator.isValid()); } public void testIsValidBad() throws Exception { String noDTD = test_Constants.XML_DECLARATION + test_Constants.CHUCK_JONES_RIP_XML; validator = new Validator(new StringReader(noDTD)); - assertEquals("noDTD " + validator.toString(), - false, validator.isValid()); + assertFalse("noDTD " + validator.toString(), validator.isValid()); // test XMLTestCase + failXMLTestCaseTest(noDTD); failXMLTestCaseTest(validator); String dtdTwice = test_Constants.XML_DECLARATION @@ -166,18 +163,18 @@ + test_Constants.CHUCK_JONES_RIP_DTD_DECL + test_Constants.CHUCK_JONES_RIP_XML; validator = new Validator(new StringReader(dtdTwice)); - assertEquals("dtdTwice " + validator.toString(), - false, validator.isValid()); + assertFalse("dtdTwice " + validator.toString(), validator.isValid()); // test XMLTestCase + failXMLTestCaseTest(dtdTwice); failXMLTestCaseTest(validator); String invalidXML = test_Constants.XML_DECLARATION + test_Constants.CHUCK_JONES_RIP_DTD_DECL + test_Constants.CHUCK_JONES_SPINNING_IN_HIS_GRAVE_XML; validator = new Validator(new StringReader(invalidXML)); - assertEquals("invalidXML " + validator.toString(), - false, validator.isValid()); + assertFalse("invalidXML " + validator.toString(), validator.isValid()); // test XMLTestCase + failXMLTestCaseTest(invalidXML); failXMLTestCaseTest(validator); } @@ -209,13 +206,22 @@ // ---- XMLTestCase methods ---- private void passXMLTestCaseTest(String xml) throws Exception { assertXMLValid(xml); + assertXMLValid(new InputSource(new StringReader(xml))); + assertXMLValid(new InputSource(new StringBufferInputStream(xml))); } private void passXMLTestCaseTest(String xml, String systemId) throws Exception { assertXMLValid(xml, systemId); + assertXMLValid(new InputSource(new StringReader(xml)), systemId); + assertXMLValid(new InputSource(new StringBufferInputStream(xml)), + systemId); } private void passXMLTestCaseTest(String xml, String systemId, String doctype) throws Exception { assertXMLValid(xml, systemId, doctype); + assertXMLValid(new InputSource(new StringReader(xml)), systemId, + doctype); + assertXMLValid(new InputSource(new StringBufferInputStream(xml)), + systemId, doctype); } private void passXMLTestCaseTest(Validator validator) throws Exception { assertXMLValid(validator); @@ -227,7 +233,40 @@ } catch (AssertionFailedError e) { // expecting this } + try { + assertXMLValid(new InputSource(new StringReader(xml)), systemId); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } + try { + assertXMLValid(new InputSource(new StringBufferInputStream(xml)), + systemId); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } } + private void failXMLTestCaseTest(String xml) throws Exception { + try { + assertXMLValid(xml); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } + try { + assertXMLValid(new InputSource(new StringReader(xml))); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } + try { + assertXMLValid(new InputSource(new StringBufferInputStream(xml))); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } + } private void failXMLTestCaseTest(String xml, String systemId, String doctype) throws Exception { try { @@ -236,6 +275,20 @@ } catch (AssertionFailedError e) { // expecting this } + try { + assertXMLValid(new InputSource(new StringReader(xml)), systemId, + doctype); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } + try { + assertXMLValid(new InputSource(new StringBufferInputStream(xml)), + systemId, doctype); + fail("Expected assertion to fail!"); + } catch (AssertionFailedError e) { + // expecting this + } } private void failXMLTestCaseTest(Validator validator) throws Exception { try { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-28 04:06:23
|
Revision: 158 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=158&view=rev Author: bodewig Date: 2007-03-27 21:06:22 -0700 (Tue, 27 Mar 2007) Log Message: ----------- Allow custom URI resolvers Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java 2007-03-27 04:31:56 UTC (rev 157) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java 2007-03-28 04:06:22 UTC (rev 158) @@ -191,10 +191,13 @@ throws ConfigurationException { try { TransformerFactory factory = XMLUnit.getTransformerFactory(); - if (stylesheetSource == null) { - return factory.newTransformer(); + Transformer t = stylesheetSource == null + ? factory.newTransformer() + : factory.newTransformer(stylesheetSource); + if (XMLUnit.getURIResolver() != null) { + t.setURIResolver(XMLUnit.getURIResolver()); } - return factory.newTransformer(stylesheetSource); + return t; } catch (javax.xml.transform.TransformerConfigurationException ex) { throw new ConfigurationException(ex); } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java 2007-03-27 04:31:56 UTC (rev 157) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java 2007-03-28 04:06:22 UTC (rev 158) @@ -43,6 +43,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; import java.io.IOException; import java.io.Reader; @@ -62,6 +63,7 @@ private static DocumentBuilderFactory testBuilderFactory; private static TransformerFactory transformerFactory; private static boolean ignoreWhitespace = false; + private static URIResolver uriResolver = null; private static EntityResolver testEntityResolver = null; private static EntityResolver controlEntityResolver = null; private static NamespaceContext namespaceContext = null; @@ -443,8 +445,21 @@ return transformerFactory; } + /** + * Sets the URIResolver to use during transformations. + */ + public static void setURIResolver(URIResolver resolver) { + uriResolver = resolver; + } /** + * Gets the URIResolver used during Transformations. + */ + public static URIResolver getURIResolver() { + return uriResolver; + } + + /** * Override the SAX parser to use in tests. * Currently only used by {@link Validator Validator class} * @param className This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-27 04:31:57
|
Revision: 157 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=157&view=rev Author: bodewig Date: 2007-03-26 21:31:56 -0700 (Mon, 26 Mar 2007) Log Message: ----------- Add InputSource as possible input Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeTest.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeTest.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeTest.java 2007-03-27 04:05:20 UTC (rev 156) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeTest.java 2007-03-27 04:31:56 UTC (rev 157) @@ -45,6 +45,7 @@ import org.w3c.dom.traversal.DocumentTraversal; import org.w3c.dom.traversal.NodeFilter; import org.w3c.dom.traversal.NodeIterator; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** @@ -76,6 +77,14 @@ } /** + * Construct a NodeTest for the DOM built using the InputSource. + */ + public NodeTest(InputSource src) throws SAXException, + IOException { + this(XMLUnit.buildDocument(XMLUnit.newControlParser(), src)); + } + + /** * Construct a NodeTest for the specified Document * @exception IllegalArgumentException if the Document does not support the DOM * DocumentTraversal interface (most DOM implementations should provide this Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java 2007-03-27 04:05:20 UTC (rev 156) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java 2007-03-27 04:31:56 UTC (rev 157) @@ -53,8 +53,10 @@ import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.InputSource; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -91,6 +93,26 @@ } /** + * Create a transformation using InputSource input XML and + * InputSource stylesheet + * @param input + * @param stylesheet + */ + public Transform(InputSource input, InputSource stylesheet) { + this(new SAXSource(input), new SAXSource(stylesheet)); + } + + /** + * Create a transformation using InputSource input XML and + * stylesheet in a File + * @param input + * @param stylesheet + */ + public Transform(InputSource input, File stylesheet) { + this(new SAXSource(input), new StreamSource(stylesheet)); + } + + /** * Create a transformation that allows us to serialize a DOM Node * @param source */ Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java 2007-03-27 04:05:20 UTC (rev 156) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java 2007-03-27 04:31:56 UTC (rev 157) @@ -41,6 +41,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.io.StringReader; import org.w3c.dom.Document; import org.xml.sax.ErrorHandler; @@ -83,14 +84,27 @@ private Boolean isValid; /** + * Kept for backwards compatibility. + * @deprecated Use the protected three arg constructor instead. + */ + protected Validator(InputSource inputSource, + boolean usingDoctypeReader) + throws SAXException, ConfigurationException { + this(inputSource, null, usingDoctypeReader); + } + + /** * Baseline constructor: called by all others * * @param inputSource + * @param systemId * @param usingDoctypeReader * @throws SAXException * @throws ConfigurationException if validation could not be turned on */ - protected Validator(InputSource inputSource, boolean usingDoctypeReader) + protected Validator(InputSource inputSource, + String systemId, + boolean usingDoctypeReader) throws SAXException, ConfigurationException { isValid = null; messages = new StringBuffer(); @@ -103,6 +117,9 @@ } this.validationInputSource = inputSource; + if (systemId != null) { + validationInputSource.setSystemId(systemId); + } this.usingDoctypeReader = usingDoctypeReader; } @@ -137,11 +154,38 @@ */ public Validator(Reader readerForValidation) throws SAXException, ConfigurationException { - this(new InputSource(readerForValidation), - (readerForValidation instanceof DoctypeReader)); + this(readerForValidation, null); } /** + * Basic constructor. + * Validates the contents of the String using the DTD or schema referenced + * by those contents. + * + * @param stringForValidation + * @throws SAXException if unable to obtain new Sax parser via JAXP factory + * @throws ConfigurationException if validation could not be turned on + */ + public Validator(String stringForValidation) + throws SAXException, ConfigurationException { + this(new StringReader(stringForValidation)); + } + + /** + * Basic constructor. + * Validates the contents of the InputSource using the DTD or + * schema referenced by those contents. + * + * @param readerForValidation + * @throws SAXException if unable to obtain new Sax parser via JAXP factory + * @throws ConfigurationException if validation could not be turned on + */ + public Validator(InputSource sourceForValidation) + throws SAXException, ConfigurationException { + this(sourceForValidation, null); + } + + /** * Extended constructor. * Validates the contents of the Reader using the DTD specified with the * systemID. There must be DOCTYPE instruction in the markup that @@ -155,11 +199,46 @@ */ public Validator(Reader readerForValidation, String systemID) throws SAXException, ConfigurationException { - this(readerForValidation); - validationInputSource.setSystemId(systemID); + this(new InputSource(readerForValidation), systemID, + (readerForValidation instanceof DoctypeReader)); } /** + * Extended constructor. + * Validates the contents of the String using the DTD specified with the + * systemID. There must be DOCTYPE instruction in the markup that + * references the DTD or else the markup will be considered invalid: if + * there is no DOCTYPE in the markup use the 3-argument constructor + * + * @param stringForValidation + * @param systemID + * @throws SAXException if unable to obtain new Sax parser via JAXP factory + * @throws ConfigurationException if validation could not be turned on + */ + public Validator(String stringForValidation, String systemID) + throws SAXException, ConfigurationException { + this(new StringReader(stringForValidation), systemID); + } + + /** + * Extended constructor. + * Validates the contents of the InputSource using the DTD + * specified with the systemID. There must be DOCTYPE instruction + * in the markup that references the DTD or else the markup will + * be considered invalid: if there is no DOCTYPE in the markup use + * the 3-argument constructor + * + * @param sourceForValidation + * @param systemID + * @throws SAXException if unable to obtain new Sax parser via JAXP factory + * @throws ConfigurationException if validation could not be turned on + */ + public Validator(InputSource sourceForValidation, String systemID) + throws SAXException, ConfigurationException { + this(sourceForValidation, systemID, false); + } + + /** * Full constructor. * Validates the contents of the Reader using the DTD specified with the * systemID and named with the doctype name. @@ -172,8 +251,8 @@ */ public Validator(Reader readerForValidation, String systemID, String doctype) throws SAXException, ConfigurationException { - this(new DoctypeReader(readerForValidation, doctype, systemID)); - validationInputSource.setSystemId(systemID); + this(new DoctypeReader(readerForValidation, doctype, systemID), + systemID); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-27 04:05:29
|
Revision: 156 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=156&view=rev Author: bodewig Date: 2007-03-26 21:05:20 -0700 (Mon, 26 Mar 2007) Log Message: ----------- Using XMLUnit section added Modified Paths: -------------- trunk/xmlunit/src/site/XMLUnit-Java.xml Modified: trunk/xmlunit/src/site/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 20:01:39 UTC (rev 155) +++ trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-27 04:05:20 UTC (rev 156) @@ -126,7 +126,7 @@ unrecoverable differences</emphasis> between them.</para> </section> - <section><title>Configuring XMLUnit</title> + <section id="configuring-intro"><title>Configuring XMLUnit</title> <para>There are many Java XML parsers available, and XMLUnit should work with any JAXP compliant parser library, such as @@ -137,8 +137,8 @@ transformation engine is required, such as Xalan-J<footnote id="xalan-link"><para><ulink url="http://xalan.apache.org/">http://xalan.apache.org/</ulink></para></footnote>, - from the Software Foundation. To configure XMLUnit to use a - specific parser and transformation engine set three System + from the Apache Software Foundation. To configure XMLUnit to + use a specific parser and transformation engine set three System properties before any tests are run, e.g.</para> <example><title>Configuring JAXP via System Properties</title> @@ -152,15 +152,9 @@ ]]></programlisting> </example> - <para>If you are using a JDK 1.4 or later, your Java class - library already contain the required XML parsers and XSLT - transformers. Still you may want to use a different - parser/transformer than the one of your JDK - in particular - since the versions shipping with some JDKs are known to contain - serious bugs. You may also want to review the <ulink - url="http://java.sun.com/j2se/1.4.2/docs/guide/standards/">Endorsed - Standards Override Mechanism</ulink> to use a different - parser/transformer than the one of your JDK.</para> + <para>You may want to read <xref linkend="JAXP"/> for more + details - in particular if you are using Java 1.4 or + later.</para> <para>Alternatively there are static methods on the XMLUnit class that can be called directly. The advantage of this @@ -178,10 +172,6 @@ ]]></programlisting> </example> - <para>The later approach should also work for JDK 1.4 and above, - even if you don't override the endorsed standards - libraries</para> - </section> <section><title>Writing XML comparison tests</title> @@ -386,7 +376,8 @@ </section> - <section><title>Comparing XML Transformations</title> + <section id="transform-intro"> + <title>Comparing XML Transformations</title> <para>XMLUnit can test XSL transformations at a high level using the <literal>Transform</literal> class that wraps an @@ -667,20 +658,304 @@ <section id="Using"><title>Using XMLUnit</title> + <section id="requirements"> + <title>Requirements</title> + + <para>XMLUnit requires a JAXP compliant XML parser virtually + everywhere. Several features of XMLUnit also require a JAXP + compliant XSLT transformer. If it is avaliable, a JAXP + compliant XPath engine will be used for XPath tests.</para> + + <para>To build XMLUnit at least JAXP 1.2 is required, this is + the version provided by the Java class library in JDK 1.4. The + JAXP 1.3 (i.e. Java5 and above) XPath engine can only be built + when JAXP 1.3 is available.</para> + + <para>As long as you don't require support for XML Namespaces or + XML Schema, any JAXP 1.1 compliant implementations should work + at runtime. For namespace and schema support you will need a + parser that complies to JAXP 1.2 and supports the required + feature. The XML parser shipping with JDK 1.4 (a version of + Apache Crimson) for example is compliant to JAXP 1.2 but doesn't + support Schema validation.</para> + + <para>XMLUnit is supposed to build and run on any Java version + after 1.3 (at least no new hard JDK 1.4 dependencies have been + added in XMLUnit 1.1), but it has only been tested on JDK 1.4.2 + and above.</para> + + <para>To build XMLUnit JUnit 3.x (only tested with JUnit 3.8.x) + is required. It is not required at runtime unless you intend to + use the <literal>XMLTestCase</literal> or + <literal>XMLAssert</literal> classes.</para> + </section> + <section id="using-plain"> <title>Basic Usage</title> - <section id="input-choices"> - <title>Providing Input to XMLUnit</title> + <para>XMLUnit consists of a few classes all living in the + <literal>org.custommonkey.xmlunit</literal> package. You can + use these classes directly from your code, no matter whether you + are writing a unit test or want to use XMLUnit's features for + any other purpose.</para> + + <para>This section provides a few hints of where to start if you + want to use a certain feature of XMLUnit, more details can be + found in the more specific sections later in this + document.</para> + + <section><title>Comparing Pieces of XML</title> + + <para>Heart and soul of XMLUnit's comparison engine is + <literal>DifferenceEngine</literal> but most of the time you + will use it indirectly via the <literal>Diff</literal> + class.</para> + + <para>You can influence the engine by providing (custom) + implementations for various interfaces and by setting a couple + of options on the <literal>XMLUnit</literal> class.</para> + + <para>More information is available in <xref + linkend="Comparing"/>.</para> + </section> + + <section><title>Validating</title> + + <para>All validation happens in the + <literal>Validator</literal> class. The default is to + validate against a DTD, but XML Schema validation can be + enabled by an option (see + <literal>Validator.useXMLSchema</literal>).</para> + + <para>Several options of the <literal>XMLUnit</literal> class + affect validation.</para> + + <para>More information is available in <xref + linkend="Validating"/>.</para> + + </section> + + <section><title>XSLT Transformations</title> + + <para>The <literal>Transform</literal> class provides an easy + to use layer on top of JAXP's transformations. An instance of + this class is initialized with the source document and a + stylesheet and the result of the transformation can be + retrieved as a <literal>String</literal> or DOM + <literal>Document</literal>.</para> + + <para>The output of <literal>Transform</literal> can be used + as input to comparisions, validations, XPath tests and so on. + There is no detailed sections on transformations since they + are really only a different way to create input for the rest + of XMLUnit's machinery. Examples can be found in <xref + linkend="transform-intro"/>.</para> + + <para>You can access the underlying XSLT transformer via + <literal>XMLUnit.getTransformerFactory</literal>.</para> + </section> + + <section> + <title>XPath Engine</title> + + <para>The central piece of XMLUnit's XPath support is the + <literal>XpathEngine</literal> interface. Currently two + implementations of the interface exist, + <literal>SimpleXpathEngine</literal> and + <literal>org.custommonkey.xmlunit.jaxp13.Jaxp13XpathEngine</literal>.</para> + + <para><literal>SimpleXpathEngine</literal> is a very basic + implementation that uses your XSLT transformer under the + covers. This also means it will expose you to the bugs found + in your transformer like the transformer claiming a stylesheet + couldn't be compiled for very basic XPath expressions. This + has been reported to be the case for JDK 1.5.</para> + + <para><literal>org.custommonkey.xmlunit.jaxp13.Jaxp13XpathEngine</literal> + uses JAXP 1.3's <literal>javax.xml.xpath</literal> package and + seems to work more reliable, stable and performant than + <literal>SimpleXpathEngine</literal>.</para> + + <para>You use the <literal>XMLUnit.newXpathEngine</literal> + method to obtain an instance of the + <literal>XpathEngine</literal>. As of XMLUnit 1.1 this will + try to use JAXP 1.3 if it is available and fall back to + <literal>SimpleXpathEngine</literal>.</para> + + <para>Instances of <literal>XpathEngine</literal> can return + the results of XPath queries either as DOM + <literal>NodeList</literal> or plain + <literal>String</literal>s.</para> + + <para>More information is available in <xref + linkend="XPath"/>.</para> + </section> + + <section> + <title>DOM Tree Walking</title> + + <para>To test pieces of XML by traversing the DOM tree you use + the <literal>NodeTester</literal> class. Each DOm + <literal>Node</literal> will be passed to a + <literal>NodeTester</literal> implementation you provide. The + <literal>AbstractNodeTester</literal> class is provided as a + NullObject pattern base class for your implementations of your + own.</para> + + <para>More information is available in <xref + linkend="NodeTest"/>.</para> + </section> </section> <section id="junit3"> <title>Using XMLUnit With JUnit 3.x</title> + + <para>Initially XMLUnit was tightly coupled to JUnit and the + recommended approach was to write unit tests by inheriting from + <literal>XMLTestCase</literal>. <literal>XMLTestCase</literal> + provides a pretty long list of <literal>assert...</literal> + methods that may simplify your interaction with XMLUnit's + internals in many common cases.</para> + + <para>The <literal>XMLAssert</literal> class provides the same + set of <literal>assert...</literal>s as static methods. Use + <literal>XMLAssert</literal> instead of + <literal>XMLTestCase</literal> for your unit tests if you can't + or don't want to inherit from + <literal>XMLTestCase</literal>.</para> + + <para>All power of XMLUnit is available whether you use + <literal>XMLTestCase</literal> and/or + <literal>XMLAssert</literal> or the underlying API directly. If + you are using JUnit 3.x then using the specifc classes may prove + to be more convenient.</para> + </section> + + <section id="common-config"> + <title>Common Configuration Options</title> + + <section id="JAXP"> + <title>JAXP</title> + + <para>If you are using a JDK 1.4 or later, your Java class + library already contains the required XML parsers and XSLT + transformers. Still you may want to use a different + parser/transformer than the one of your JDK - in particular + since the versions shipping with some JDKs are known to + contain serious bugs.</para> + + <para>As described in <xref linkend="configuring-intro"/> + there are two main approaches to choose the XML parser of XSLT + transformer: System properties and setters in the + <literal>XMLUnit</literal> class.</para> + + <para>If you use system properties you have the advantage that + your choice affects the whole JAXP system, whether it is used + inside of XMLUnit or not. If you are using JDK 1.4 or later + you may also want to review the <ulink + url="http://java.sun.com/j2se/1.4.2/docs/guide/standards/">Endorsed + Standards Override Mechanism</ulink> to use a different + parser/transformer than the one shipping with your JDK.</para> + + <para>The second option - using the <literal>XMLUnit</literal> + class - allows you to use different parsers for control and + test documents, it even allows you to use different parsers + for different test cases, if you really want to stretch it + that far. It may also work for JDK 1.4 and above, even if you + don't override the endorsed standards libraries.</para> + + <para>You can access the underlying JAXP parser by + <literal>XMLUnit.newControlParser</literal>, + <literal>XMLUnit.newTestParser</literal>, + <literal>XMLUnit.getControlDocumentBuilderFactory</literal>, + <literal>XMLUnit.getTestDocumentBuilderFactory</literal> and + <literal>XMLUnit.getSAXParserFactory</literal> (used by + Validator). The various <literal>build...</literal> methods + in <literal>XMLUnit</literal> provide convenience layers for + building DOM <literal>Document</literal>s using the configured + parsers.</para> + + </section> + + <section> + <title><literal>EntityResolver</literal></title> + + <para>You can provide a custom + <literal>org.xml.sax.EntityResolver</literal> for the control + and test parsers via + <literal>XMLUnit.setControlEntityResolver</literal> and + <literal>XMLUnit.setTestEntityResolver</literal>.</para> + </section> + + <section id="element-content-whitespace"> + <title>Element Content Whitespace</title> + + <para>Element content whitespace - also known as ignorable + whitespace - is whitespace contained in elements whose content + model doesn't allow text content. I.e. the newline and space + characters between <literal><![CDATA[<foo>]]></literal> and + <literal><![CDATA[<bar>]]></literal> in the following example + belongs into this category.</para> + + <programlisting language="XML"><![CDATA[ +<foo> + <bar/></foo> +]]></programlisting> + + <para>Using <literal>XMLUnit.setIgnoreWhitespace</literal> it + is possible to make the test and control parser ignore this + kind of whitespace.</para> + </section> + </section> + + <section id="input-choices"> + <title>Providing Input to XMLUnit</title> + + <para>Most methods in XMLUnit that expect a piece of XML as + input provide several overloads that obtain their input from + different sources. The most common options are:</para> + + <itemizedlist> + + <listitem>A DOM <literal>Document</literal>. + + <para>Here you have all control over the document's + creation. Such a <literal>Document</literal> could as well + be the result of an XSLT transformation via the + <literal>Transform</literal> class.</para> + </listitem> + + <listitem>A <literal>String</literal>. + + <para>Here a DOM <literal>Document</literal> is built from + the input <literal>String</literal> using the JAXP parser + specified for control or test documents - depending on + whether the input is a control or test piece of XML.</para> + </listitem> + + <listitem>A <literal>Reader</literal>. + + <para>Here a DOM <literal>Document</literal> is built from + the input <literal>Reader</literal> using the JAXP parser + specified for control or test documents - depending on + whether the input is a control or test piece of XML.</para> + + <para>Note that using a <literal>Reader</literal> is a + bad choice if your XML encoding is different from your + platform's default encoding since Java's IO system won't + read your XML declaration. It is a good practice to use one + of the other overloads rather than the + <literal>Reader</literal> version to ensure encoding has + been dealt with properly.</para> + </listitem> + </itemizedlist> + </section> + </section> - <section id="Comparing"><title>Comparing XML documents</title> + <section id="Comparing"><title>Comparing Pieces of XML</title> <section id="comparing-basics"> <title>The Difference Engine</title> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-23 20:01:41
|
Revision: 155 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=155&view=rev Author: bodewig Date: 2007-03-23 13:01:39 -0700 (Fri, 23 Mar 2007) Log Message: ----------- Add changes content Modified Paths: -------------- trunk/xmlunit/src/site/XMLUnit-Java.xml Modified: trunk/xmlunit/src/site/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 19:57:40 UTC (rev 154) +++ trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 20:01:39 UTC (rev 155) @@ -756,16 +756,142 @@ <section id="changes-1.1"> <title>Changes from XMLUnit 1.0 to 1.1</title> + <para>XMLUnit 1.1's main focus was to add two features that have + been asked for repeatedly:</para> + + <itemizedlist> + <listitem>Support for XML namespaces in XPath + processing</listitem> + + <listitem>Support for XML Schema validation.</listitem> + </itemizedlist> + + <para>In addition some JAXP features that have been added after + the release of XMLUnit 1.0 are now supported - most notably + XPath support - and all reported bugs and feature requests have + been addressed.</para> + <section id="breaking-changes-1.1"> <title>Breaking Changes</title> + + <itemizedlist> + <listitem> + <literal>XMLTestCase</literal> is now abstract. There is + no reason why you should have created instances of this + class without subclassing it, but if you did, your code + will now break. You will most likely want to look at the + <literal>XMLAssert</literal> class. + </listitem> + + <listitem> + <para>All methods that have been declared to throw + <literal>TransformerConfigurationException</literal> or + <literal>ParserConfigurationException</literal> now no + longer declare it. Exceptions of these types cannot be + recovered from anyway, so XMLUnit will now wrap them in a + <literal>org.custommonkey.xmlunit.exceptions.ConfigurationException</literal> + which is an unchecked exception.</para> + + <para>This change doesn't have a big impact on your tests, + but if you tried to catch these exceptions they will now + bypass your catch blocks.</para> + </listitem> + </itemizedlist> </section> <section id="features-1.1"> <title>New Features</title> + + <itemizedlist> + <listitem>XMLUnit 1.0 shipped with rudimentary support for + XML Schema validation (it worked with Apache Xerces-J but no + other parsers). XMLUnit 1.1 supports Schema validation for + any JAXP compliant XML parser (that supports Schema itself). + You can also tell XMLUnit where to look for the XML Schema + definitions. See <xref linkend="validating-schema"/> for + details.</listitem> + + <listitem>XPath support has undergone significant changes, + see <xref linkend="XPath"/> for more details. In particular + XMLUnit will now use <literal>javax.xml.xpath</literal> if + it is available (which also helps to avoid the buggy XSLTC + version that is the default transformer engine in Java 5) + and supports XML namespaces.</listitem> + + <listitem>Several new configuration options have been added, + see <xref linkend="comparing-config"/>. + <itemizedlist> + <listitem>Treat CDATA sections and Texts alike. <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=1262148&group_id=23187&atid=377768">Issue + 1262148</ulink>.</listitem> + + <listitem>Ignore differences in Text whitespace. <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=754812&group_id=23187&atid=377771">Issue + 754812</ulink>.</listitem> + + <listitem>Ignore comments completely. <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=707255&group_id=23187&atid=377770">Issue + 707255</ulink>.</listitem> + </itemizedlist> + </listitem> + + <listitem> + <para>A new package + <literal>org.custommonkey.xmlunit.examples</literal> has + been added that showcases some of XMLUnit's abilities. + It currently contains two classes:</para> + + <orderedlist> + <listitem> + <literal>MultiLevelElementNameAndTextQualifier</literal> + see <xref linkend="ElementQualifier"/> for a + description.</listitem> + + <listitem><literal>XPathRegexAssert</literal> that + provides a JUnit 3.x like + <literal>assertXPathMatches</literal> method to verify + that the stringified value of an XPath match matches a + given regular expression (requires JDK 1.4 or + above).</listitem> + </orderedlist> + </listitem> + </itemizedlist> </section> <section id="bugfixes-1.1"> - <title>Bug Fixes</title> + <title>Important Bug Fixes</title> + + <itemizedlist> + <listitem><literal>ElementNameAndAttributeQualifier</literal> + would throw an <literal>NullPointerException</literal> if + the control piece of XML contained attributes that were + missing in the test piece of XML. <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=952920&group_id=23187&atid=377768">Issue + 952920</ulink>.</listitem> + + <listitem> + <literal>XMLTestCase.assertXMLNotEqual(String, Reader, + Reader)</literal> delegated to + <literal>assertXMLEqual</literal> instead of + <literal>assertXMLNotEqual</literal> internally, negating + the assertion's logic. <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=956372&group_id=23187&atid=377768">Issue + 956372</ulink>.</listitem> + + <listitem>Under certain circumstances the reported XPath + expressions for nodes that showed differences were wrong. + XMLUnit could lose the root element or errornously append an + extra attribute name. Issues <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=1047364&group_id=23187&atid=377768">1047364</ulink> + and <ulink url="http://sourceforge.net/tracker/index.php?func=detail&aid=1027863&group_id=23187&atid=377770">1027863</ulink>.</listitem> + + <listitem> + <literal>TolerantSaxParser</literal>'s logic in + <literal>characters</literal> was broken and could cause + <literal>StringIndexOutOfBoundsException</literal>s. + <ulink + url="http://sourceforge.net/tracker/index.php?func=detail&aid=1150234&group_id=23187&atid=377768">Issue 1150234</ulink>.</listitem> + </itemizedlist> </section> </section> </appendix> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-23 19:57:41
|
Revision: 154 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=154&view=rev Author: bodewig Date: 2007-03-23 12:57:40 -0700 (Fri, 23 Mar 2007) Log Message: ----------- add test for forum thread 1691528 Modified Paths: -------------- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java Modified: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java 2007-03-23 04:49:34 UTC (rev 153) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java 2007-03-23 19:57:40 UTC (rev 154) @@ -192,7 +192,35 @@ // sequence of nodes assertEquals(3, l.size()); } + + /** + * @see http://sourceforge.net/forum/forum.php?thread_id=1691528&forum_id=73274 + */ + public void testHelpForumThread1691528() throws Exception { + String control = "<table border=\"1\">" + + "<tr>" + + "<th>News</th>" + + "</tr>" + + "<tr>" + + "<td>Newsitem 1</td>" + + "</tr>" + + "</table>"; + String test = "<table border=\"1\">" + + "<tr>" + + "<th>News</th>" + + "</tr>" + + "<tr>" + + "<td>Newsitem 2</td>" + + "<td>Newsitem 1</td>" + + "</tr>" + + "</table>"; + DetailedDiff diff = new DetailedDiff(new Diff(control, test)); + List changes = diff.getAllDifferences(); + // number of children, text of first child + assertEquals(2, changes.size()); + } + protected Diff buildDiff(Document control, Document test) { return new DetailedDiff(super.buildDiff(control, test)); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-23 04:49:35
|
Revision: 153 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=153&view=rev Author: bodewig Date: 2007-03-22 21:49:34 -0700 (Thu, 22 Mar 2007) Log Message: ----------- re-indent, only whitespace changes Modified Paths: -------------- trunk/xmlunit/src/site/XMLUnit-Java.xml Modified: trunk/xmlunit/src/site/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 04:40:11 UTC (rev 152) +++ trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 04:49:34 UTC (rev 153) @@ -49,93 +49,100 @@ XMLUnit, but not the only one. XMLUnit's features can be fully used without any dependency on JUnit at all.</para> - <section><title>What is XMLUnit?</title> + <section><title>What is XMLUnit?</title> - <para>XMLUnit enables JUnit-style assertions to be made about the - content and structure of XML<footnote id="more on JUnit"><para>For - more information on JUnit see <ulink - url="http://www.junit.org">http://www.junit.org</ulink></para></footnote>. It - is an open source project hosted at <ulink url="http://xmlunit.sourceforge.net/">http://xmlunit.sourceforge.net/</ulink> - that grew out of a need to test a system that generated and - received custom XML messages. The problem that we faced was how to - verify that the system generated the correct message from a known - set of inputs. Obviously we could use a DTD or a schema to - validate the message output, but this approach wouldn't allow us - to distinguish between valid XML with correct content (e.g. - element <literal><![CDATA[<foo>bar</foo>]]></literal>) and valid - XML with incorrect content (e.g. element - <literal><![CDATA[<foo>baz</foo>]]></literal>). What we really - wanted was an <literal>assertXMLEquals()</literal> method, so we - could compare the message that we expected the system to generate - and the message that the system actually generated. And that was - the beginning of XMLUnit.</para> - </section> - <section><title>Quick tour</title> + <para>XMLUnit enables JUnit-style assertions to be made about + the content and structure of XML<footnote id="more on + JUnit"><para>For more information on JUnit see <ulink + url="http://www.junit.org">http://www.junit.org</ulink></para></footnote>. It + is an open source project hosted at <ulink + url="http://xmlunit.sourceforge.net/">http://xmlunit.sourceforge.net/</ulink> + that grew out of a need to test a system that generated and + received custom XML messages. The problem that we faced was how + to verify that the system generated the correct message from a + known set of inputs. Obviously we could use a DTD or a schema to + validate the message output, but this approach wouldn't allow us + to distinguish between valid XML with correct content (e.g. + element <literal><![CDATA[<foo>bar</foo>]]></literal>) and valid + XML with incorrect content (e.g. element + <literal><![CDATA[<foo>baz</foo>]]></literal>). What we really + wanted was an <literal>assertXMLEquals()</literal> method, so we + could compare the message that we expected the system to + generate and the message that the system actually generated. And + that was the beginning of XMLUnit.</para> + </section> + <section><title>Quick tour</title> - <para>XMLUnit provides a single JUnit extension class, - <literal>XMLTestCase</literal>, and a set of supporting classes - that allow assertions to be made about:</para> + <para>XMLUnit provides a single JUnit extension class, + <literal>XMLTestCase</literal>, and a set of supporting classes + that allow assertions to be made about:</para> - <itemizedlist> - <listitem>The differences between two pieces of XML (via - <literal>Diff</literal> and <literal>DetailedDiff</literal> - classes)</listitem> + <itemizedlist> + <listitem>The differences between two pieces of XML (via + <literal>Diff</literal> and <literal>DetailedDiff</literal> + classes)</listitem> - <listitem>The validity of a piece of XML (via - <literal>Validator</literal> class)</listitem> + <listitem>The validity of a piece of XML (via + <literal>Validator</literal> class)</listitem> - <listitem> The outcome of transforming a piece of XML using XSLT - (via <literal>Transform</literal> class)</listitem> + <listitem> The outcome of transforming a piece of XML using + XSLT (via <literal>Transform</literal> class)</listitem> - <listitem>The evaluation of an XPath expression on a piece of - XML (via classes implementing the <literal>XpathEngine</literal> interface)</listitem> + <listitem>The evaluation of an XPath expression on a piece of + XML (via classes implementing the + <literal>XpathEngine</literal> interface)</listitem> - <listitem>Individual nodes in a piece of XML that are exposed by - DOM Traversal (via <literal>NodeTest</literal> class)</listitem> - </itemizedlist> + <listitem>Individual nodes in a piece of XML that are exposed + by DOM Traversal (via <literal>NodeTest</literal> + class)</listitem> + </itemizedlist> - <para>XMLUnit can also treat HTML content, even badly-formed HTML, - as valid XML to allow these assertions to be made about web pages - (via the <literal>HTMLDocumentBuilder</literal> class).</para> - </section> + <para>XMLUnit can also treat HTML content, even badly-formed + HTML, as valid XML to allow these assertions to be made about + web pages (via the <literal>HTMLDocumentBuilder</literal> + class).</para> + </section> - <section><title>Glossary</title> + <section><title>Glossary</title> - <para>As with many projects some words in XMLUnit have particular - meanings so here is a quick overview. A <emphasis>piece</emphasis> - of XML is a DOM Document, a String containing marked-up content, - or a Source or Reader that allows access to marked-up content - within some resource. XMLUnit compares the expected - <emphasis>control</emphasis> XML to some actual - <emphasis>test</emphasis> XML. The comparison can reveal that two - pieces of XML are <emphasis>identical</emphasis>, - <emphasis>similar</emphasis> or - <emphasis>different</emphasis>. The unit of measurement used by - the comparison is a <emphasis>difference</emphasis>, and - differences can be either <emphasis>recoverable</emphasis> or - <emphasis>unrecoverable</emphasis>. Two pieces of XML are - <emphasis>identical</emphasis> if there are <emphasis>no - differences</emphasis> between them, <emphasis>similar</emphasis> - if there are <emphasis>only recoverable differences</emphasis> - between them, and <emphasis>different</emphasis> if there are - <emphasis>any unrecoverable differences</emphasis> between - them.</para> - </section> + <para>As with many projects some words in XMLUnit have + particular meanings so here is a quick overview. A + <emphasis>piece</emphasis> of XML is a DOM Document, a String + containing marked-up content, or a Source or Reader that allows + access to marked-up content within some resource. XMLUnit + compares the expected <emphasis>control</emphasis> XML to some + actual <emphasis>test</emphasis> XML. The comparison can reveal + that two pieces of XML are <emphasis>identical</emphasis>, + <emphasis>similar</emphasis> or + <emphasis>different</emphasis>. The unit of measurement used by + the comparison is a <emphasis>difference</emphasis>, and + differences can be either <emphasis>recoverable</emphasis> or + <emphasis>unrecoverable</emphasis>. Two pieces of XML are + <emphasis>identical</emphasis> if there are <emphasis>no + differences</emphasis> between them, + <emphasis>similar</emphasis> if there are <emphasis>only + recoverable differences</emphasis> between them, and + <emphasis>different</emphasis> if there are <emphasis>any + unrecoverable differences</emphasis> between them.</para> + </section> - <section><title>Configuring XMLUnit</title> + <section><title>Configuring XMLUnit</title> - <para>There are many Java XML parsers available, and XMLUnit - should work with any JAXP compliant parser library, such as Xerces-J - <footnote id="xerces-link"><para><ulink url="http://xerces.apache.org/">http://xerces.apache.org/</ulink></para></footnote> - from the Apache Software Foundation. To use the XSL and XPath features - of XMLUnit a Trax (the XSLT portion of JAXP) compliant transformation engine is required, - such as Xalan-J<footnote id="xalan-link"><para><ulink url="http://xalan.apache.org/">http://xalan.apache.org/</ulink></para></footnote>, - from the Software Foundation. To configure - XMLUnit to use a specific parser and transformation engine set three - System properties before any tests are run, e.g.</para> + <para>There are many Java XML parsers available, and XMLUnit + should work with any JAXP compliant parser library, such as + Xerces-J <footnote id="xerces-link"><para><ulink + url="http://xerces.apache.org/">http://xerces.apache.org/</ulink></para></footnote> + from the Apache Software Foundation. To use the XSL and XPath + features of XMLUnit a Trax (the XSLT portion of JAXP) compliant + transformation engine is required, such as Xalan-J<footnote + id="xalan-link"><para><ulink + url="http://xalan.apache.org/">http://xalan.apache.org/</ulink></para></footnote>, + from the Software Foundation. To configure XMLUnit to use a + specific parser and transformation engine set three System + properties before any tests are run, e.g.</para> - <example><title>Configuring JAXP via System Properties</title> - <programlisting language="Java"><![CDATA[ + <example><title>Configuring JAXP via System Properties</title> + <programlisting language="Java"><![CDATA[ System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); System.setProperty("javax.xml.parsers.SAXParserFactory", @@ -143,7 +150,7 @@ System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); ]]></programlisting> - </example> + </example> <para>If you are using a JDK 1.4 or later, your Java class library already contain the required XML parsers and XSLT @@ -155,36 +162,36 @@ Standards Override Mechanism</ulink> to use a different parser/transformer than the one of your JDK.</para> - <para>Alternatively there are static methods on the XMLUnit class - that can be called directly. The advantage of this approach is - that you can specify a different parser class for control and test - XML and change the current parser class at any time in your tests, - should you need to make assertions about the compatibility of - different parsers.</para> + <para>Alternatively there are static methods on the XMLUnit + class that can be called directly. The advantage of this + approach is that you can specify a different parser class for + control and test XML and change the current parser class at any + time in your tests, should you need to make assertions about the + compatibility of different parsers.</para> -<example><title>Configuring JAXP via XMLUnit class</title> - <programlisting language="Java"><![CDATA[ + <example><title>Configuring JAXP via XMLUnit class</title> + <programlisting language="Java"><![CDATA[ XMLUnit.setControlParser("org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); XMLUnit.setTestParser("org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); XMLUnit.setSAXParserFactory("org.apache.xerces.jaxp.SAXParserFactoryImpl"); XMLUnit.setTransformerFactory("org.apache.xalan.processor.TransformerFactoryImpl"); ]]></programlisting> - </example> + </example> <para>The later approach should also work for JDK 1.4 and above, even if you don't override the endorsed standards libraries</para> - </section> + </section> - <section><title>Writing XML comparison tests</title> + <section><title>Writing XML comparison tests</title> - <para>Let's say we have two pieces of XML that we wish to compare - and assert that they are equal. We could write a simple test class - like this:</para> + <para>Let's say we have two pieces of XML that we wish to + compare and assert that they are equal. We could write a simple + test class like this:</para> - <example><title>A simple comparison test</title> - <programlisting language="Java"><![CDATA[ + <example><title>A simple comparison test</title> + <programlisting language="Java"><![CDATA[ public class MyXMLTestCase extends XMLTestCase { public MyXMLTestCase(String name) { super(name); @@ -198,36 +205,36 @@ } }]]></programlisting></example> - <para>The <literal>assertXMLEqual</literal> test will pass if the - control and test XML are either similar or identical. Obviously in - this case the pieces of XML are different and the test will - fail. The failure message indicates both what the difference is - and the Xpath locations of the nodes that were being - compared:</para> + <para>The <literal>assertXMLEqual</literal> test will pass if + the control and test XML are either similar or + identical. Obviously in this case the pieces of XML are + different and the test will fail. The failure message indicates + both what the difference is and the Xpath locations of the nodes + that were being compared:</para> - <programlisting><![CDATA[ + <programlisting><![CDATA[ Comparing test xml to control xml [different] Expected element tag name 'uuid' but was 'localId' - comparing <uuid...> at /msg[1]/uuid[1] to <localId...> at /msg[1]/localId[1] ]]></programlisting> - <para>When comparing pieces of XML, the - <literal>XMLTestCase</literal> actually creates an instance of the - <literal>Diff</literal> class. The <literal>Diff</literal> class - stores the result of an XML comparison and makes it available - through the methods <literal>similar()</literal> and - <literal>identical()</literal>. The - <literal>assertXMLEquals()</literal> method tests the value of - <literal>Diff.similar()</literal> and the - <literal>assertXMLIdentical()</literal> method tests the value of - <literal>Diff.identical()</literal>.</para> + <para>When comparing pieces of XML, the + <literal>XMLTestCase</literal> actually creates an instance of + the <literal>Diff</literal> class. The <literal>Diff</literal> + class stores the result of an XML comparison and makes it + available through the methods <literal>similar()</literal> and + <literal>identical()</literal>. The + <literal>assertXMLEquals()</literal> method tests the value of + <literal>Diff.similar()</literal> and the + <literal>assertXMLIdentical()</literal> method tests the value + of <literal>Diff.identical()</literal>.</para> - <para>It is easy to create a <literal>Diff</literal> instance - directly without using the <literal>XMLTestCase</literal> class as - below:</para> + <para>It is easy to create a <literal>Diff</literal> instance + directly without using the <literal>XMLTestCase</literal> class + as below:</para> - <example><title>Creating a <literal>Diff</literal> - instance</title> - <programlisting language="Java"><![CDATA[ + <example><title>Creating a <literal>Diff</literal> + instance</title> + <programlisting language="Java"><![CDATA[ public void testXMLIdentical()throws Exception { String myControlXML = "<struct><int>3</int><boolean>false</boolean></struct>"; @@ -240,27 +247,27 @@ myDiff.identical()); }]]></programlisting></example> - <para>This test fails as two pieces of XML are similar but not - identical if their nodes occur in a different sequence. The - failure message reported by JUnit from the call to - <literal>myDiff.toString()</literal> looks like this:</para> + <para>This test fails as two pieces of XML are similar but not + identical if their nodes occur in a different sequence. The + failure message reported by JUnit from the call to + <literal>myDiff.toString()</literal> looks like this:</para> - <programlisting><![CDATA[ + <programlisting><![CDATA[ [not identical] Expected sequence of child nodes '0' but was '1' - comparing <int...> at /struct[1]/int[1] to <int...> at /struct[1]/int[1] ]]></programlisting> - <para>For efficiency reasons a <literal>Diff</literal> stops the - comparison process as soon as the first difference is found. To - get all the differences between two pieces of XML an instance of - the <literal>DetailedDiff</literal> class, a subclass of - <literal>Diff</literal>, is required. Note that a - <literal>DetailedDiff</literal> is constructed using an existing - <literal>Diff</literal> instance.</para> + <para>For efficiency reasons a <literal>Diff</literal> stops the + comparison process as soon as the first difference is found. To + get all the differences between two pieces of XML an instance of + the <literal>DetailedDiff</literal> class, a subclass of + <literal>Diff</literal>, is required. Note that a + <literal>DetailedDiff</literal> is constructed using an existing + <literal>Diff</literal> instance.</para> - <para>Consider this test that uses a DetailedDiff:</para> + <para>Consider this test that uses a DetailedDiff:</para> - <example><title>Using <literal>DetailedDiff</literal></title> - <programlisting language="Java"><![CDATA[ + <example><title>Using <literal>DetailedDiff</literal></title> + <programlisting language="Java"><![CDATA[ public void testAllDifferences() throws Exception { String myControlXML = "<news><item id=\"1\">War</item>" + "<item id=\"2\">Plague</item>" @@ -273,47 +280,47 @@ assertEquals(myDiff.toString(), 2, allDifferences.size()); }]]></programlisting></example> - <para>This test fails with the message below as each of the 3 news - items differs between the control and test XML:</para> + <para>This test fails with the message below as each of the 3 + news items differs between the control and test XML:</para> - <programlisting><![CDATA[ + <programlisting><![CDATA[ [different] Expected text value 'War' but was 'Peace' - comparing <item...>War</item> at /news[1]/item[1]/text()[1] to <item...>Peace</item> at /news[1]/item[1]/text()[1] [different] Expected text value 'Plague' but was 'Health' - comparing <item...>Plague</item> at /news[1]/item[2]/text()[1] to <item...>Health</item> at /news[1]/item[2]/text()[1] [different] Expected text value 'Famine' but was 'Plenty' - comparing <item...>Famine</item> at /news[1]/item[3]/text()[1] to <item...>Plenty</item> at /news[1]/item[3]/text()[1] expected <2> but was <3> ]]></programlisting> - <para>The List returned from the - <literal>getAllDifferences()</literal> method contains - <literal>Difference</literal> instances. These instances describe - both the type<footnote id="DifferenceConstants"><para>A full set - of prototype <literal>Difference</literal> instances - one for - each type of difference - is defined using final static fields in - the <literal>DifferenceConstants</literal> - class.</para></footnote> of difference found between a control - node and test node and the <literal>NodeDetail</literal> of those - nodes (including the XPath location of each - node). <literal>Difference</literal> instances are passed at - runtime in notification events to a registered - <literal>DifferenceListener</literal>, an interface whose default - implementation is provided by the <literal>Diff</literal> - class.</para> + <para>The List returned from the + <literal>getAllDifferences()</literal> method contains + <literal>Difference</literal> instances. These instances + describe both the type<footnote id="DifferenceConstants"><para>A + full set of prototype <literal>Difference</literal> instances - + one for each type of difference - is defined using final static + fields in the <literal>DifferenceConstants</literal> + class.</para></footnote> of difference found between a control + node and test node and the <literal>NodeDetail</literal> of + those nodes (including the XPath location of each + node). <literal>Difference</literal> instances are passed at + runtime in notification events to a registered + <literal>DifferenceListener</literal>, an interface whose + default implementation is provided by the + <literal>Diff</literal> class.</para> - <para>However it is possible to override this default behaviour by - implementing the interface in your own class. The - <literal>IgnoreTextAndAttributeValuesDifferenceListener</literal> - class is an example of how to implement a custom - <literal>DifferenceListener</literal>. It allows an XML comparison - to be made that ignores differences in the values of text and - attribute nodes, for example when comparing a skeleton or outline - piece of XML to some generated XML.</para> + <para>However it is possible to override this default behaviour + by implementing the interface in your own class. The + <literal>IgnoreTextAndAttributeValuesDifferenceListener</literal> + class is an example of how to implement a custom + <literal>DifferenceListener</literal>. It allows an XML + comparison to be made that ignores differences in the values of + text and attribute nodes, for example when comparing a skeleton + or outline piece of XML to some generated XML.</para> - <para>The following test illustrates the use of a custom - <literal>DifferenceListener</literal>:</para> + <para>The following test illustrates the use of a custom + <literal>DifferenceListener</literal>:</para> - <example><title>Using a custom - <literal>DifferenceListener</literal></title> - <programlisting language="Java"><![CDATA[ + <example><title>Using a custom + <literal>DifferenceListener</literal></title> + <programlisting language="Java"><![CDATA[ public void testCompareToSkeletonXML() throws Exception { String myControlXML = "<location><street-address>22 any street</street-address><postcode>XY00 99Z</postcode></location>"; String myTestXML = "<location><street-address>20 east cheap</street-address><postcode>EC3M 1EB</postcode></location>"; @@ -324,41 +331,44 @@ myDiff.similar()); }]]></programlisting></example> - <para>The <literal>DifferenceEngine</literal> class generates the - events that are passed to a <literal>DifferenceListener</literal> - implementation as two pieces of XML are compared. Using recursion - it navigates through the nodes in the control XML DOM, and - determines which node in the test XML DOM qualifies for comparison - to the current control node. The qualifying test node will match - the control node's node type, as well as the node name and - namespace (if defined for the control node).</para> + <para>The <literal>DifferenceEngine</literal> class generates + the events that are passed to a + <literal>DifferenceListener</literal> implementation as two + pieces of XML are compared. Using recursion it navigates through + the nodes in the control XML DOM, and determines which node in + the test XML DOM qualifies for comparison to the current control + node. The qualifying test node will match the control node's + node type, as well as the node name and namespace (if defined + for the control node).</para> - <para>However when the control node is an - <literal>Element</literal>, it is less straightforward to - determine which test <literal>Element</literal> qualifies for - comparison as the parent node may contain repeated child - <literal>Element</literal>s with the same name and namespace. So - for <literal>Element</literal> nodes, an instance of the - <literal>ElementQualifier</literal> interface is used determine - whether a given test <literal>Element</literal> node qualifies for - comparison with a control <literal>Element</literal> node. This - separates the decision about whether two - <literal>Elements</literal> should be compared from the decision - about whether those two <literal>Elements</literal> are considered - similar. By default an <literal>ElementNameQualifier</literal> - class is used that compares the nth child - <literal><![CDATA[<abc>]]></literal> test element to the nth child - <literal><![CDATA[<abc>]]></literal> control element, i.e. the - sequence of the child elements in the test XML is - important. However this default behaviour can be overridden using - an <literal>ElementNameAndTextQualifier</literal> or - <literal>ElementNameAndAttributesQualifier</literal>.</para> + <para>However when the control node is an + <literal>Element</literal>, it is less straightforward to + determine which test <literal>Element</literal> qualifies for + comparison as the parent node may contain repeated child + <literal>Element</literal>s with the same name and namespace. So + for <literal>Element</literal> nodes, an instance of the + <literal>ElementQualifier</literal> interface is used determine + whether a given test <literal>Element</literal> node qualifies + for comparison with a control <literal>Element</literal> + node. This separates the decision about whether two + <literal>Elements</literal> should be compared from the decision + about whether those two <literal>Elements</literal> are + considered similar. By default an + <literal>ElementNameQualifier</literal> class is used that + compares the nth child <literal><![CDATA[<abc>]]></literal> test + element to the nth child <literal><![CDATA[<abc>]]></literal> + control element, i.e. the sequence of the child elements in the + test XML is important. However this default behaviour can be + overridden using an + <literal>ElementNameAndTextQualifier</literal> or + <literal>ElementNameAndAttributesQualifier</literal>.</para> - <para>The test below demonstrates the use of a custom - <literal>ElementQualifier</literal>:</para> + <para>The test below demonstrates the use of a custom + <literal>ElementQualifier</literal>:</para> - <example><title>Using a custom <literal>ElementQualifier</literal></title> - <programlisting language="Java"><![CDATA[ + <example><title>Using a custom + <literal>ElementQualifier</literal></title> + <programlisting language="Java"><![CDATA[ public void testRepeatedChildElements() throws Exception { String myControlXML = "<suite>" + "<test status=\"pass\">FirstTestCase</test>" @@ -374,19 +384,19 @@ myDiff, true); }]]></programlisting></example> - </section> + </section> - <section><title>Comparing XML Transformations</title> + <section><title>Comparing XML Transformations</title> - <para>XMLUnit can test XSL transformations at a high level using - the <literal>Transform</literal> class that wraps an - <literal>javax.xml.transform.Transformer</literal> - instance. Knowing the input XML, input stylesheet and expected - output XML we can assert that the output of the transformation - matches the expected output as follows:</para> + <para>XMLUnit can test XSL transformations at a high level using + the <literal>Transform</literal> class that wraps an + <literal>javax.xml.transform.Transformer</literal> + instance. Knowing the input XML, input stylesheet and expected + output XML we can assert that the output of the transformation + matches the expected output as follows:</para> - <example><title>Testing the Result of a Transformation</title> - <programlisting language="Java"><![CDATA[ + <example><title>Testing the Result of a Transformation</title> + <programlisting language="Java"><![CDATA[ public void testXSLTransformation() throws Exception { String myInputXML = "..."; File myStylesheetFile = new File("..."); @@ -396,14 +406,15 @@ assertTrue("XSL transformation worked as expected", myDiff.similar()); }]]></programlisting></example> - <para>The <literal>getResultString()</literal> and - <literal>getResultDocument()</literal> methods of the - <literal>Transform</literal> class can be used to access the - result of the XSL transformation programmatically if required, for - example as below:</para> + <para>The <literal>getResultString()</literal> and + <literal>getResultDocument()</literal> methods of the + <literal>Transform</literal> class can be used to access the + result of the XSL transformation programmatically if required, + for example as below:</para> - <example><title>Using <literal>Transform</literal> programmatically</title> - <programlisting language="Java"><![CDATA[ + <example><title>Using <literal>Transform</literal> + programmatically</title> + <programlisting language="Java"><![CDATA[ public void testAnotherXSLTransformation() throws Exception { File myInputXMLFile = new File("..."); File myStylesheetFile = new File("..."); @@ -418,21 +429,21 @@ assertTrue("XSL transformation worked as expected", myDiff.similar()); }]]></programlisting></example> - </section> + </section> - <section><title>Validation Tests</title> + <section><title>Validation Tests</title> - <para>XML parsers that validate a piece of XML against a DTD are - common, however they rely on a DTD reference being present in the - XML, and they can only validate against a single DTD. When writing - a system that exchanges XML messages with third parties there are - times when you would like to validate the XML against a DTD that - is not available to the recipient of the message and so cannot be - referenced in the message itself. XMLUnit provides a - <literal>Validator</literal> class for this purpose.</para> + <para>XML parsers that validate a piece of XML against a DTD are + common, however they rely on a DTD reference being present in + the XML, and they can only validate against a single DTD. When + writing a system that exchanges XML messages with third parties + there are times when you would like to validate the XML against + a DTD that is not available to the recipient of the message and + so cannot be referenced in the message itself. XMLUnit provides + a <literal>Validator</literal> class for this purpose.</para> - <example><title>Validating Against a DTD</title> - <programlisting language="Java"><![CDATA[ + <example><title>Validating Against a DTD</title> + <programlisting language="Java"><![CDATA[ public void testValidation() throws Exception { XMLUnit.getTestDocumentBuilderFactory().setValidating(true); // As the document is parsed it is validated against its referenced DTD @@ -450,18 +461,18 @@ or more XML Schema definitions. See <xref linkend="validating-schema"/> for details.</para> - </section> + </section> - <section><title>Xpath Tests</title> + <section><title>Xpath Tests</title> - <para>One of the strengths of XML is the ability to - programmatically extract specific parts of a document using XPath - expressions. The <literal>XMLTestCase</literal> class offers a - number of XPath related assertion methods, as demonstrated in this - test:</para> + <para>One of the strengths of XML is the ability to + programmatically extract specific parts of a document using + XPath expressions. The <literal>XMLTestCase</literal> class + offers a number of XPath related assertion methods, as + demonstrated in this test:</para> - <example><title>Using Xpath Tests</title> - <programlisting language="Java"><![CDATA[ + <example><title>Using Xpath Tests</title> + <programlisting language="Java"><![CDATA[ public void testXPaths() throws Exception { String mySolarSystemXML = "<solar-system>" + "<planet name='Earth' position='3' supportsLife='yes'/>" @@ -476,24 +487,24 @@ mySolarSystemXML); }]]></programlisting></example> - <para>When an XPath expression is evaluated against a piece of XML - a <literal>NodeList</literal> is created that contains the - matching <literal>Node</literal>s. The methods in the previous - test <literal>assertXPathExists</literal>, - <literal>assertNotXPathExists</literal>, - <literal>assertXPathsEqual</literal>, and - <literal>assertXPathsNotEqual</literal> use these - <literal>NodeList</literal>s. However, the contents of a - <literal>NodeList</literal> can be flattened (or - <literal>String</literal>-ified) to a single value, and XMLUnit - also allows assertions to be made about this single value, as in - this test<footnote id="XpathEngine note"><para>Each of the - <literal>assertXpath...()</literal> methods uses an implementation of the - <literal>XpathEngine</literal> interface to evaluate an Xpath - expression.</para></footnote>:</para> + <para>When an XPath expression is evaluated against a piece of + XML a <literal>NodeList</literal> is created that contains the + matching <literal>Node</literal>s. The methods in the previous + test <literal>assertXPathExists</literal>, + <literal>assertNotXPathExists</literal>, + <literal>assertXPathsEqual</literal>, and + <literal>assertXPathsNotEqual</literal> use these + <literal>NodeList</literal>s. However, the contents of a + <literal>NodeList</literal> can be flattened (or + <literal>String</literal>-ified) to a single value, and XMLUnit + also allows assertions to be made about this single value, as in + this test<footnote id="XpathEngine note"><para>Each of the + <literal>assertXpath...()</literal> methods uses an + implementation of the <literal>XpathEngine</literal> interface + to evaluate an Xpath expression.</para></footnote>:</para> - <example><title>Testing Xpath Values</title> - <programlisting language="Java"><![CDATA[ + <example><title>Testing Xpath Values</title> + <programlisting language="Java"><![CDATA[ public void testXPathValues() throws Exception { String myJavaFlavours = "<java-flavours>" + "<jvm current='some platforms'>1.1.x</jvm>" @@ -508,27 +519,28 @@ "//jvm[3]/@current", myJavaFlavours); }]]></programlisting></example> - <para>Xpaths are especially useful where a document is made up - largely of known, unchanging content with only a small amount of - changing content created by the system. One of the main areas - where constant "boilerplate" markup is combined with system - generated markup is of course in web applications. The power of - XPath expressions can make testing web page output quite trivial, - and XMLUnit supplies a means of converting even very badly formed - HTML into XML to aid this approach to testing.</para> + <para>Xpaths are especially useful where a document is made up + largely of known, unchanging content with only a small amount of + changing content created by the system. One of the main areas + where constant "boilerplate" markup is combined with system + generated markup is of course in web applications. The power of + XPath expressions can make testing web page output quite + trivial, and XMLUnit supplies a means of converting even very + badly formed HTML into XML to aid this approach to + testing.</para> - <para>The <literal>HTMLDocumentBuilder</literal> class uses the - Swing HTML parser to convert marked-up content to Sax events. The - <literal>TolerantSaxDocumentBuilder</literal> class handles the - Sax events to build up a DOM document in a tolerant fashion - i.e. without mandating that opened elements are closed. (In a - purely XML world this class would have no purpose as there are - plenty of Sax event handlers that can build DOM documents from - well formed content). The test below illustrates how the use of - these classes:</para> + <para>The <literal>HTMLDocumentBuilder</literal> class uses the + Swing HTML parser to convert marked-up content to Sax + events. The <literal>TolerantSaxDocumentBuilder</literal> class + handles the Sax events to build up a DOM document in a tolerant + fashion i.e. without mandating that opened elements are + closed. (In a purely XML world this class would have no purpose + as there are plenty of Sax event handlers that can build DOM + documents from well formed content). The test below illustrates + how the use of these classes:</para> - <example><title>Working with non well-formed HTML</title> - <programlisting language="Java"><![CDATA[ + <example><title>Working with non well-formed HTML</title> + <programlisting language="Java"><![CDATA[ public void testXpathsInHTML() throws Exception { String someBadlyFormedHTML = "<html><title>Ugh</title>" + "<body><h1>Heading<ul>" @@ -543,36 +555,36 @@ wellFormedDocument); }]]></programlisting></example> - <para>One of the key points about using Xpaths with HTML content - is that extracting values in tests requires the values to be - identifiable. (This is just another way of saying that testing - HTML is easier when it is written to be testable.) In the previous - example id attributes were used to identify the list item values - that needed to be testable, however class attributes or span and - div tags can also be used to identify specific content for - testing.</para> + <para>One of the key points about using Xpaths with HTML content + is that extracting values in tests requires the values to be + identifiable. (This is just another way of saying that testing + HTML is easier when it is written to be testable.) In the + previous example id attributes were used to identify the list + item values that needed to be testable, however class attributes + or span and div tags can also be used to identify specific + content for testing.</para> - </section> + </section> - <section><title>Testing by Tree Walking</title> + <section><title>Testing by Tree Walking</title> - <para>The DOM specification allows a <literal>Document</literal> - to optionally implement the <literal>DocumentTraversal</literal> - interface. This interface allows an application to iterate over - the <literal>Node</literal>s contained in a - <literal>Document</literal>, or to "walk the DOM tree". The - XMLUnit <literal>NodeTest</literal> class and - <literal>NodeTester</literal> interface make use of - <literal>DocumentTraversal</literal> to expose individual - <literal>Node</literal>s in tests: the former handles the - mechanics of iteration, and the latter allows custom test - strategies to be implemented. A sample test strategy is supplied - by the <literal>CountingNodeTester</literal> class that counts the - nodes presented to it and compares the actual count to an expected - count. The test below illustrates its use:</para> + <para>The DOM specification allows a <literal>Document</literal> + to optionally implement the <literal>DocumentTraversal</literal> + interface. This interface allows an application to iterate over + the <literal>Node</literal>s contained in a + <literal>Document</literal>, or to "walk the DOM tree". The + XMLUnit <literal>NodeTest</literal> class and + <literal>NodeTester</literal> interface make use of + <literal>DocumentTraversal</literal> to expose individual + <literal>Node</literal>s in tests: the former handles the + mechanics of iteration, and the latter allows custom test + strategies to be implemented. A sample test strategy is supplied + by the <literal>CountingNodeTester</literal> class that counts + the nodes presented to it and compares the actual count to an + expected count. The test below illustrates its use:</para> - <example><title>Using <literal>CountingNodeTester</literal></title> - <programlisting language="Java"><![CDATA[ + <example><title>Using <literal>CountingNodeTester</literal></title> + <programlisting language="Java"><![CDATA[ public void testCountingNodeTester() throws Exception { String testXML = "<fibonacci><val>1</val><val>2</val><val>3</val>" + "<val>5</val><val>9</val></fibonacci>"; @@ -580,34 +592,34 @@ assertNodeTestPasses(testXML, countingNodeTester, Node.TEXT_NODE); }]]></programlisting></example> - <para>This test fails as there are 5 text nodes, and JUnit - supplies the following message:</para> + <para>This test fails as there are 5 text nodes, and JUnit + supplies the following message:</para> - <programlisting> + <programlisting> Expected node test to pass, but it failed! Counted 5 node(s) but expected 4 - </programlisting> + </programlisting> - <para>Note that if your DOM implementation does not support the - <literal>DocumentTraversal</literal> interface then XMLUnit will - throw an <literal>IllegalArgumentException</literal> informing you - that you cannot use the <literal>NodeTest</literal> or - <literal>NodeTester</literal> classes. Unfortunately even if your - DOM implementation does support - <literal>DocumentTraversal</literal>, attributes are not exposed - by iteration: however they can be examined from the - <literal>Element</literal> node that contains them.</para> + <para>Note that if your DOM implementation does not support the + <literal>DocumentTraversal</literal> interface then XMLUnit will + throw an <literal>IllegalArgumentException</literal> informing + you that you cannot use the <literal>NodeTest</literal> or + <literal>NodeTester</literal> classes. Unfortunately even if + your DOM implementation does support + <literal>DocumentTraversal</literal>, attributes are not exposed + by iteration: however they can be examined from the + <literal>Element</literal> node that contains them.</para> - <para>While the previous test could have been easily performed - using XPath, there are times when <literal>Node</literal> - iteration is more powerful. In general, this is true when there - are programmatic relationships between nodes that can be more - easily tested iteratively. The following test uses a custom - <literal>NodeTester</literal> class to illustrate the - potential:</para> + <para>While the previous test could have been easily performed + using XPath, there are times when <literal>Node</literal> + iteration is more powerful. In general, this is true when there + are programmatic relationships between nodes that can be more + easily tested iteratively. The following test uses a custom + <literal>NodeTester</literal> class to illustrate the + potential:</para> - <example><title>Using a Custom <literal>NodeTester</literal></title> - <programlisting language="Java"><![CDATA[ + <example><title>Using a Custom <literal>NodeTester</literal></title> + <programlisting language="Java"><![CDATA[ public void testCustomNodeTester() throws Exception { String testXML = "<fibonacci><val>1</val><val>2</val><val>3</val>" + "<val>5</val><val>9</val></fibonacci>"; @@ -643,12 +655,12 @@ } }]]></programlisting></example> - <para>The test fails because the XML contains the wrong value for - the last number in the sequence:</para> + <para>The test fails because the XML contains the wrong value + for the last number in the sequence:</para> - <programlisting> + <programlisting> Expected node test to pass, but it failed! Incorrect value [#text: 9] - </programlisting> + </programlisting> </section> </section> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-23 04:40:11
|
Revision: 152 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=152&view=rev Author: bodewig Date: 2007-03-22 21:40:11 -0700 (Thu, 22 Mar 2007) Log Message: ----------- Add outline of planned doc Modified Paths: -------------- trunk/xmlunit/src/site/XMLUnit-Java.xml Modified: trunk/xmlunit/src/site/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 04:37:22 UTC (rev 151) +++ trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-23 04:40:11 UTC (rev 152) @@ -2,7 +2,7 @@ <!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.1b1//EN" "http://docbook.org/xml/simple/1.1b1/sdocbook.dtd"> <article> - <title>A Tour of XMLUnit + <title>XMLUnit Java User's Guide <inlinemediaobject><imageobject> <imagedata fileref="xmlunit.png" width="331" depth="100" valign="middle" format="PNG"/> @@ -15,6 +15,12 @@ <surname>Bacon</surname> </author> </authorgroup> + <authorgroup> + <author> + <firstname>Stefan</firstname> + <surname>Bodewig</surname> + </author> + </authorgroup> <revhistory> <revision> <revnumber>1.0</revnumber> @@ -25,16 +31,31 @@ </author> <revremark>Documentation for XMLUnit Java 1.0</revremark> </revision> + <revision> + <revnumber>1.1</revnumber> + <date>... 2007</date> + <revremark>Documentation for XMLUnit Java 1.1</revremark> + </revision> </revhistory> </articleinfo> + <section><title>A Tour of XMLUnit</title> + + <para>This first section contains a tour through XMLUnit's + features, the next sections will cover them in more detail.</para> + + <para>Note that it has a strong focus on using the + <literal>XMLTestCase</literal> class which is one option to use + XMLUnit, but not the only one. XMLUnit's features can be fully + used without any dependency on JUnit at all.</para> + <section><title>What is XMLUnit?</title> <para>XMLUnit enables JUnit-style assertions to be made about the content and structure of XML<footnote id="more on JUnit"><para>For more information on JUnit see <ulink url="http://www.junit.org">http://www.junit.org</ulink></para></footnote>. It - is an open source project hosted at http://xmlunit.sourceforge.net + is an open source project hosted at <ulink url="http://xmlunit.sourceforge.net/">http://xmlunit.sourceforge.net/</ulink> that grew out of a need to test a system that generated and received custom XML messages. The problem that we faced was how to verify that the system generated the correct message from a known @@ -67,7 +88,7 @@ (via <literal>Transform</literal> class)</listitem> <listitem>The evaluation of an XPath expression on a piece of - XML (via <literal>SimpleXpathEngine</literal> class)</listitem> + XML (via classes implementing the <literal>XpathEngine</literal> interface)</listitem> <listitem>Individual nodes in a piece of XML that are exposed by DOM Traversal (via <literal>NodeTest</literal> class)</listitem> @@ -104,11 +125,13 @@ <section><title>Configuring XMLUnit</title> <para>There are many Java XML parsers available, and XMLUnit - should work with any JAXP compliant parser library, such as Xerces - from the Apache Jakarta project. To use the XSL and XPath features - of XMLUnit a Trax compliant transformation engine is required, - such as Xalan, from the Apache Jakarta project. To configure - XMLUnit to use your parser and transformation engine set three + should work with any JAXP compliant parser library, such as Xerces-J + <footnote id="xerces-link"><para><ulink url="http://xerces.apache.org/">http://xerces.apache.org/</ulink></para></footnote> + from the Apache Software Foundation. To use the XSL and XPath features + of XMLUnit a Trax (the XSLT portion of JAXP) compliant transformation engine is required, + such as Xalan-J<footnote id="xalan-link"><para><ulink url="http://xalan.apache.org/">http://xalan.apache.org/</ulink></para></footnote>, + from the Software Foundation. To configure + XMLUnit to use a specific parser and transformation engine set three System properties before any tests are run, e.g.</para> <example><title>Configuring JAXP via System Properties</title> @@ -122,6 +145,16 @@ ]]></programlisting> </example> + <para>If you are using a JDK 1.4 or later, your Java class + library already contain the required XML parsers and XSLT + transformers. Still you may want to use a different + parser/transformer than the one of your JDK - in particular + since the versions shipping with some JDKs are known to contain + serious bugs. You may also want to review the <ulink + url="http://java.sun.com/j2se/1.4.2/docs/guide/standards/">Endorsed + Standards Override Mechanism</ulink> to use a different + parser/transformer than the one of your JDK.</para> + <para>Alternatively there are static methods on the XMLUnit class that can be called directly. The advantage of this approach is that you can specify a different parser class for control and test @@ -137,6 +170,11 @@ XMLUnit.setTransformerFactory("org.apache.xalan.processor.TransformerFactoryImpl"); ]]></programlisting> </example> + + <para>The later approach should also work for JDK 1.4 and above, + even if you don't override the endorsed standards + libraries</para> + </section> <section><title>Writing XML comparison tests</title> @@ -407,6 +445,11 @@ myValidator.isValid()); }]]></programlisting></example> + <para>Starting with XMLUnit 1.1, the + <literal>Validator</literal> class can also validate against one + or more XML Schema definitions. See <xref + linkend="validating-schema"/> for details.</para> + </section> <section><title>Xpath Tests</title> @@ -444,9 +487,9 @@ <literal>NodeList</literal> can be flattened (or <literal>String</literal>-ified) to a single value, and XMLUnit also allows assertions to be made about this single value, as in - this test<footnote id="SimpleXpathEngine note"><para>Each of the - <literal>assertXpath...()</literal> methods uses the - <literal>SimpleXpathEngine</literal> class to evaluate an Xpath + this test<footnote id="XpathEngine note"><para>Each of the + <literal>assertXpath...()</literal> methods uses an implementation of the + <literal>XpathEngine</literal> interface to evaluate an Xpath expression.</para></footnote>:</para> <example><title>Testing Xpath Values</title> @@ -607,5 +650,112 @@ Expected node test to pass, but it failed! Incorrect value [#text: 9] </programlisting> + </section> </section> + + <section id="Using"><title>Using XMLUnit</title> + + <section id="using-plain"> + <title>Basic Usage</title> + + <section id="input-choices"> + <title>Providing Input to XMLUnit</title> + </section> + </section> + + <section id="junit3"> + <title>Using XMLUnit With JUnit 3.x</title> + </section> + </section> + + <section id="Comparing"><title>Comparing XML documents</title> + + <section id="comparing-basics"> + <title>The Difference Engine</title> + </section> + + <section id="comparing-junit3"> + <title>JUnit 3.x Convenience Methods</title> + </section> + + <section id="comparing-config"> + <title>Configuration Options</title> + </section> + + <section id="ElementQualifier"> + <title><literal>ElementQualifier</literal></title> + </section> + + <section id="DifferenceListener"> + <title><literal>DifferenceListener</literal></title> + </section> + + <section id="ComparisonController"> + <title><literal>ComparisonController</literal></title> + </section> + </section> + + <section id="Validating"><title>Validating XML documents</title> + + <section id="validating-basics"> + <title>The <literal>Validator</literal> class</title> + + <section id="validating-dtd"> + <title>DTD Validation</title> + </section> + + <section id="validating-schema"> + <title>XML Schema Validation</title> + </section> + </section> + + <section id="validation-junit3"> + <title>JUnit 3.x Convenience Methods</title> + </section> + + <section id="validation-config"> + <title>Configuration Options</title> + </section> + </section> + + <section id="XPath"> + <title>XPath Tests</title> + + <section id="xpath-engines"> + <title>XPath Engines</title> + </section> + + <section id="xpath-junit3"> + <title>JUnit 3.x Convenience Methods</title> + </section> + + <section id="xpath-config"> + <title>Configuration Options</title> + </section> + </section> + + <section id="NodeTest"> + <title>DOM Tree Walking</title> + </section> + + <appendix id="changes"> + <title>Changes</title> + + <section id="changes-1.1"> + <title>Changes from XMLUnit 1.0 to 1.1</title> + + <section id="breaking-changes-1.1"> + <title>Breaking Changes</title> + </section> + + <section id="features-1.1"> + <title>New Features</title> + </section> + + <section id="bugfixes-1.1"> + <title>Bug Fixes</title> + </section> + </section> + </appendix> + </article> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-23 04:37:25
|
Revision: 151 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=151&view=rev Author: bodewig Date: 2007-03-22 21:37:22 -0700 (Thu, 22 Mar 2007) Log Message: ----------- fix issue 1683752 Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java 2007-03-22 17:11:11 UTC (rev 150) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java 2007-03-23 04:37:22 UTC (rev 151) @@ -154,11 +154,7 @@ this.controlDoc = getManipulatedDocument(controlDoc); this.testDoc = getManipulatedDocument(testDoc); this.elementQualifierDelegate = elementQualifier; - if (comparator == null) { - this.differenceEngine = new DifferenceEngine(this); - } else { - this.differenceEngine = comparator; - } + this.differenceEngine = comparator; this.messages = new StringBuffer(); } @@ -247,7 +243,8 @@ if (compared) { return; } - differenceEngine.compare(controlDoc, testDoc, this, elementQualifierDelegate); + getDifferenceEngine().compare(controlDoc, testDoc, this, + elementQualifierDelegate); compared = true; } @@ -401,4 +398,13 @@ this.elementQualifierDelegate = delegate; } + /** + * Lazily initializes the difference engine if it hasn't been set + * via a constructor. + */ + private DifferenceEngine getDifferenceEngine() { + return differenceEngine == null + ? new DifferenceEngine(this) : differenceEngine; + } + } Modified: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java 2007-03-22 17:11:11 UTC (rev 150) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java 2007-03-23 04:37:22 UTC (rev 151) @@ -179,7 +179,7 @@ assertEquals(3, l.size()); } - public void XtestSeeAllDifferencesEvenIfDiffSaysHaltComparison() throws Exception { + public void testSeeAllDifferencesEvenIfDiffSaysHaltComparison() throws Exception { String control = "<a><b/><c/></a>"; String test = "<a><c/></a>"; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-22 17:11:12
|
Revision: 150 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=150&view=rev Author: bodewig Date: 2007-03-22 10:11:11 -0700 (Thu, 22 Mar 2007) Log Message: ----------- Test for issue 1683752 Modified Paths: -------------- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java Modified: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java 2007-03-22 05:02:09 UTC (rev 149) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java 2007-03-22 17:11:11 UTC (rev 150) @@ -165,6 +165,33 @@ } } + + public void testSeeAllDifferencesEvenIfDiffWouldSayHaltComparison() throws Exception { + String control = "<a><b/><c/></a>"; + String test = "<a><c/></a>"; + + Diff d = new Diff(control, test); + DetailedDiff dd = new DetailedDiff(d); + + List l = dd.getAllDifferences(); + // number of children is different, didn't find <b/>, wrong + // sequence of nodes + assertEquals(3, l.size()); + } + + public void XtestSeeAllDifferencesEvenIfDiffSaysHaltComparison() throws Exception { + String control = "<a><b/><c/></a>"; + String test = "<a><c/></a>"; + + Diff d = new Diff(control, test); + d.similar(); + DetailedDiff dd = new DetailedDiff(d); + + List l = dd.getAllDifferences(); + // number of children is different, didn't find <b/>, wrong + // sequence of nodes + assertEquals(3, l.size()); + } protected Diff buildDiff(Document control, Document test) { return new DetailedDiff(super.buildDiff(control, test)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-03-22 05:02:14
|
Revision: 149 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=149&view=rev Author: bodewig Date: 2007-03-21 22:02:09 -0700 (Wed, 21 Mar 2007) Log Message: ----------- Add docbook version of user guide Added Paths: ----------- trunk/xmlunit/src/site/XMLUnit-Java.xml Added: trunk/xmlunit/src/site/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/site/XMLUnit-Java.xml (rev 0) +++ trunk/xmlunit/src/site/XMLUnit-Java.xml 2007-03-22 05:02:09 UTC (rev 149) @@ -0,0 +1,611 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.1b1//EN" "http://docbook.org/xml/simple/1.1b1/sdocbook.dtd"> + +<article> + <title>A Tour of XMLUnit + <inlinemediaobject><imageobject> + <imagedata fileref="xmlunit.png" width="331" depth="100" + valign="middle" format="PNG"/> + </imageobject></inlinemediaobject> + </title> + <articleinfo> + <authorgroup> + <author> + <firstname>Tim</firstname> + <surname>Bacon</surname> + </author> + </authorgroup> + <revhistory> + <revision> + <revnumber>1.0</revnumber> + <date>January 2003</date> + <author> + <firstname>Tim</firstname> + <surname>Bacon</surname> + </author> + <revremark>Documentation for XMLUnit Java 1.0</revremark> + </revision> + </revhistory> + </articleinfo> + + <section><title>What is XMLUnit?</title> + + <para>XMLUnit enables JUnit-style assertions to be made about the + content and structure of XML<footnote id="more on JUnit"><para>For + more information on JUnit see <ulink + url="http://www.junit.org">http://www.junit.org</ulink></para></footnote>. It + is an open source project hosted at http://xmlunit.sourceforge.net + that grew out of a need to test a system that generated and + received custom XML messages. The problem that we faced was how to + verify that the system generated the correct message from a known + set of inputs. Obviously we could use a DTD or a schema to + validate the message output, but this approach wouldn't allow us + to distinguish between valid XML with correct content (e.g. + element <literal><![CDATA[<foo>bar</foo>]]></literal>) and valid + XML with incorrect content (e.g. element + <literal><![CDATA[<foo>baz</foo>]]></literal>). What we really + wanted was an <literal>assertXMLEquals()</literal> method, so we + could compare the message that we expected the system to generate + and the message that the system actually generated. And that was + the beginning of XMLUnit.</para> + </section> + <section><title>Quick tour</title> + + <para>XMLUnit provides a single JUnit extension class, + <literal>XMLTestCase</literal>, and a set of supporting classes + that allow assertions to be made about:</para> + + <itemizedlist> + <listitem>The differences between two pieces of XML (via + <literal>Diff</literal> and <literal>DetailedDiff</literal> + classes)</listitem> + + <listitem>The validity of a piece of XML (via + <literal>Validator</literal> class)</listitem> + + <listitem> The outcome of transforming a piece of XML using XSLT + (via <literal>Transform</literal> class)</listitem> + + <listitem>The evaluation of an XPath expression on a piece of + XML (via <literal>SimpleXpathEngine</literal> class)</listitem> + + <listitem>Individual nodes in a piece of XML that are exposed by + DOM Traversal (via <literal>NodeTest</literal> class)</listitem> + </itemizedlist> + + <para>XMLUnit can also treat HTML content, even badly-formed HTML, + as valid XML to allow these assertions to be made about web pages + (via the <literal>HTMLDocumentBuilder</literal> class).</para> + </section> + + <section><title>Glossary</title> + + <para>As with many projects some words in XMLUnit have particular + meanings so here is a quick overview. A <emphasis>piece</emphasis> + of XML is a DOM Document, a String containing marked-up content, + or a Source or Reader that allows access to marked-up content + within some resource. XMLUnit compares the expected + <emphasis>control</emphasis> XML to some actual + <emphasis>test</emphasis> XML. The comparison can reveal that two + pieces of XML are <emphasis>identical</emphasis>, + <emphasis>similar</emphasis> or + <emphasis>different</emphasis>. The unit of measurement used by + the comparison is a <emphasis>difference</emphasis>, and + differences can be either <emphasis>recoverable</emphasis> or + <emphasis>unrecoverable</emphasis>. Two pieces of XML are + <emphasis>identical</emphasis> if there are <emphasis>no + differences</emphasis> between them, <emphasis>similar</emphasis> + if there are <emphasis>only recoverable differences</emphasis> + between them, and <emphasis>different</emphasis> if there are + <emphasis>any unrecoverable differences</emphasis> between + them.</para> + </section> + + <section><title>Configuring XMLUnit</title> + + <para>There are many Java XML parsers available, and XMLUnit + should work with any JAXP compliant parser library, such as Xerces + from the Apache Jakarta project. To use the XSL and XPath features + of XMLUnit a Trax compliant transformation engine is required, + such as Xalan, from the Apache Jakarta project. To configure + XMLUnit to use your parser and transformation engine set three + System properties before any tests are run, e.g.</para> + + <example><title>Configuring JAXP via System Properties</title> + <programlisting language="Java"><![CDATA[ +System.setProperty("javax.xml.parsers.DocumentBuilderFactory", + "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); +System.setProperty("javax.xml.parsers.SAXParserFactory", + "org.apache.xerces.jaxp.SAXParserFactoryImpl"); +System.setProperty("javax.xml.transform.TransformerFactory", + "org.apache.xalan.processor.TransformerFactoryImpl"); +]]></programlisting> + </example> + + <para>Alternatively there are static methods on the XMLUnit class + that can be called directly. The advantage of this approach is + that you can specify a different parser class for control and test + XML and change the current parser class at any time in your tests, + should you need to make assertions about the compatibility of + different parsers.</para> + +<example><title>Configuring JAXP via XMLUnit class</title> + <programlisting language="Java"><![CDATA[ +XMLUnit.setControlParser("org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); +XMLUnit.setTestParser("org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); +XMLUnit.setSAXParserFactory("org.apache.xerces.jaxp.SAXParserFactoryImpl"); +XMLUnit.setTransformerFactory("org.apache.xalan.processor.TransformerFactoryImpl"); +]]></programlisting> + </example> + </section> + + <section><title>Writing XML comparison tests</title> + + <para>Let's say we have two pieces of XML that we wish to compare + and assert that they are equal. We could write a simple test class + like this:</para> + + <example><title>A simple comparison test</title> + <programlisting language="Java"><![CDATA[ +public class MyXMLTestCase extends XMLTestCase { + public MyXMLTestCase(String name) { + super(name); + } + + public void testForEquality() throws Exception { + String myControlXML = "<msg><uuid>0x00435A8C</uuid></msg>"; + String myTestXML = "<msg><localId>2376</localId></msg>"; + assertXMLEqual("Comparing test xml to control xml", + myControlXML, myTestXML); + } +}]]></programlisting></example> + + <para>The <literal>assertXMLEqual</literal> test will pass if the + control and test XML are either similar or identical. Obviously in + this case the pieces of XML are different and the test will + fail. The failure message indicates both what the difference is + and the Xpath locations of the nodes that were being + compared:</para> + + <programlisting><![CDATA[ +Comparing test xml to control xml +[different] Expected element tag name 'uuid' but was 'localId' - comparing <uuid...> at /msg[1]/uuid[1] to <localId...> at /msg[1]/localId[1] +]]></programlisting> + + <para>When comparing pieces of XML, the + <literal>XMLTestCase</literal> actually creates an instance of the + <literal>Diff</literal> class. The <literal>Diff</literal> class + stores the result of an XML comparison and makes it available + through the methods <literal>similar()</literal> and + <literal>identical()</literal>. The + <literal>assertXMLEquals()</literal> method tests the value of + <literal>Diff.similar()</literal> and the + <literal>assertXMLIdentical()</literal> method tests the value of + <literal>Diff.identical()</literal>.</para> + + <para>It is easy to create a <literal>Diff</literal> instance + directly without using the <literal>XMLTestCase</literal> class as + below:</para> + + <example><title>Creating a <literal>Diff</literal> + instance</title> + <programlisting language="Java"><![CDATA[ +public void testXMLIdentical()throws Exception { + String myControlXML = + "<struct><int>3</int><boolean>false</boolean></struct>"; + String myTestXML = + "<struct><boolean>false</boolean><int>3</int></struct>"; + Diff myDiff = new Diff(myControlXML, myTestXML); + assertTrue("XML similar " + myDiff.toString(), + myDiff.similar()); + assertTrue("XML identical " + myDiff.toString(), + myDiff.identical()); +}]]></programlisting></example> + + <para>This test fails as two pieces of XML are similar but not + identical if their nodes occur in a different sequence. The + failure message reported by JUnit from the call to + <literal>myDiff.toString()</literal> looks like this:</para> + + <programlisting><![CDATA[ +[not identical] Expected sequence of child nodes '0' but was '1' - comparing <int...> at /struct[1]/int[1] to <int...> at /struct[1]/int[1] +]]></programlisting> + + <para>For efficiency reasons a <literal>Diff</literal> stops the + comparison process as soon as the first difference is found. To + get all the differences between two pieces of XML an instance of + the <literal>DetailedDiff</literal> class, a subclass of + <literal>Diff</literal>, is required. Note that a + <literal>DetailedDiff</literal> is constructed using an existing + <literal>Diff</literal> instance.</para> + + <para>Consider this test that uses a DetailedDiff:</para> + + <example><title>Using <literal>DetailedDiff</literal></title> + <programlisting language="Java"><![CDATA[ +public void testAllDifferences() throws Exception { + String myControlXML = "<news><item id=\"1\">War</item>" + + "<item id=\"2\">Plague</item>" + + "<item id=\"3\">Famine</item></news>"; + String myTestXML = "<news><item id=\"1\">Peace</item>" + + "<item id=\"2\">Health</item>" + + "<item id=\"3\">Plenty</item></news>"; + DetailedDiff myDiff = new DetailedDiff(new Diff(myControlXML, myTestXML)); + List allDifferences = myDiff.getAllDifferences(); + assertEquals(myDiff.toString(), 2, allDifferences.size()); +}]]></programlisting></example> + + <para>This test fails with the message below as each of the 3 news + items differs between the control and test XML:</para> + + <programlisting><![CDATA[ +[different] Expected text value 'War' but was 'Peace' - comparing <item...>War</item> at /news[1]/item[1]/text()[1] to <item...>Peace</item> at /news[1]/item[1]/text()[1] +[different] Expected text value 'Plague' but was 'Health' - comparing <item...>Plague</item> at /news[1]/item[2]/text()[1] to <item...>Health</item> at /news[1]/item[2]/text()[1] +[different] Expected text value 'Famine' but was 'Plenty' - comparing <item...>Famine</item> at /news[1]/item[3]/text()[1] to <item...>Plenty</item> at /news[1]/item[3]/text()[1] +expected <2> but was <3> +]]></programlisting> + + <para>The List returned from the + <literal>getAllDifferences()</literal> method contains + <literal>Difference</literal> instances. These instances describe + both the type<footnote id="DifferenceConstants"><para>A full set + of prototype <literal>Difference</literal> instances - one for + each type of difference - is defined using final static fields in + the <literal>DifferenceConstants</literal> + class.</para></footnote> of difference found between a control + node and test node and the <literal>NodeDetail</literal> of those + nodes (including the XPath location of each + node). <literal>Difference</literal> instances are passed at + runtime in notification events to a registered + <literal>DifferenceListener</literal>, an interface whose default + implementation is provided by the <literal>Diff</literal> + class.</para> + + <para>However it is possible to override this default behaviour by + implementing the interface in your own class. The + <literal>IgnoreTextAndAttributeValuesDifferenceListener</literal> + class is an example of how to implement a custom + <literal>DifferenceListener</literal>. It allows an XML comparison + to be made that ignores differences in the values of text and + attribute nodes, for example when comparing a skeleton or outline + piece of XML to some generated XML.</para> + + <para>The following test illustrates the use of a custom + <literal>DifferenceListener</literal>:</para> + + <example><title>Using a custom + <literal>DifferenceListener</literal></title> + <programlisting language="Java"><![CDATA[ +public void testCompareToSkeletonXML() throws Exception { + String myControlXML = "<location><street-address>22 any street</street-address><postcode>XY00 99Z</postcode></location>"; + String myTestXML = "<location><street-address>20 east cheap</street-address><postcode>EC3M 1EB</postcode></location>"; + DifferenceListener myDifferenceListener = new IgnoreTextAndAttributeValuesDifferenceListener(); + Diff myDiff = new Diff(myControlXML, myTestXML); + myDiff.overrideDifferenceListener(myDifferenceListener); + assertTrue("test XML matches control skeleton XML", + myDiff.similar()); +}]]></programlisting></example> + + <para>The <literal>DifferenceEngine</literal> class generates the + events that are passed to a <literal>DifferenceListener</literal> + implementation as two pieces of XML are compared. Using recursion + it navigates through the nodes in the control XML DOM, and + determines which node in the test XML DOM qualifies for comparison + to the current control node. The qualifying test node will match + the control node's node type, as well as the node name and + namespace (if defined for the control node).</para> + + <para>However when the control node is an + <literal>Element</literal>, it is less straightforward to + determine which test <literal>Element</literal> qualifies for + comparison as the parent node may contain repeated child + <literal>Element</literal>s with the same name and namespace. So + for <literal>Element</literal> nodes, an instance of the + <literal>ElementQualifier</literal> interface is used determine + whether a given test <literal>Element</literal> node qualifies for + comparison with a control <literal>Element</literal> node. This + separates the decision about whether two + <literal>Elements</literal> should be compared from the decision + about whether those two <literal>Elements</literal> are considered + similar. By default an <literal>ElementNameQualifier</literal> + class is used that compares the nth child + <literal><![CDATA[<abc>]]></literal> test element to the nth child + <literal><![CDATA[<abc>]]></literal> control element, i.e. the + sequence of the child elements in the test XML is + important. However this default behaviour can be overridden using + an <literal>ElementNameAndTextQualifier</literal> or + <literal>ElementNameAndAttributesQualifier</literal>.</para> + + <para>The test below demonstrates the use of a custom + <literal>ElementQualifier</literal>:</para> + + <example><title>Using a custom <literal>ElementQualifier</literal></title> + <programlisting language="Java"><![CDATA[ +public void testRepeatedChildElements() throws Exception { + String myControlXML = "<suite>" + + "<test status=\"pass\">FirstTestCase</test>" + + "<test status=\"pass\">SecondTestCase</test></suite>"; + String myTestXML = "<suite>" + + "<test status=\"pass\">SecondTestCase</test>" + + "<test status=\"pass\">FirstTestCase</test></suite>"; + assertXMLNotEqual("Repeated child elements in different sequence order are not equal by default", + myControlXML, myTestXML); + Diff myDiff = new Diff(myControlXML, myTestXML); + myDiff.overrideElementQualifier(new ElementNameAndTextQualifier()); + assertXMLEqual("But they are equal when an ElementQualifier controls which test element is compared with each control element", + myDiff, true); +}]]></programlisting></example> + + </section> + + <section><title>Comparing XML Transformations</title> + + <para>XMLUnit can test XSL transformations at a high level using + the <literal>Transform</literal> class that wraps an + <literal>javax.xml.transform.Transformer</literal> + instance. Knowing the input XML, input stylesheet and expected + output XML we can assert that the output of the transformation + matches the expected output as follows:</para> + + <example><title>Testing the Result of a Transformation</title> + <programlisting language="Java"><![CDATA[ +public void testXSLTransformation() throws Exception { + String myInputXML = "..."; + File myStylesheetFile = new File("..."); + Transform myTransform = new Transform(myInputXML, myStylesheetFile); + String myExpectedOutputXML = "..."; + Diff myDiff = new Diff(myExpectedOutputXML, myTransform); + assertTrue("XSL transformation worked as expected", myDiff.similar()); +}]]></programlisting></example> + + <para>The <literal>getResultString()</literal> and + <literal>getResultDocument()</literal> methods of the + <literal>Transform</literal> class can be used to access the + result of the XSL transformation programmatically if required, for + example as below:</para> + + <example><title>Using <literal>Transform</literal> programmatically</title> + <programlisting language="Java"><![CDATA[ +public void testAnotherXSLTransformation() throws Exception { + File myInputXMLFile = new File("..."); + File myStylesheetFile = new File("..."); + Transform myTransform = new Transform( + new StreamSource(myInputXMLFile), + new StreamSource(myStylesheetFile)); + Document myExpectedOutputXML = + XMLUnit.buildDocument(XMLUnit.getControlParser(), + new FileReader("...")); + Diff myDiff = new Diff(myExpectedOutputXML, + myTransform.getResultDocument()); + assertTrue("XSL transformation worked as expected", myDiff.similar()); +}]]></programlisting></example> + + </section> + + <section><title>Validation Tests</title> + + <para>XML parsers that validate a piece of XML against a DTD are + common, however they rely on a DTD reference being present in the + XML, and they can only validate against a single DTD. When writing + a system that exchanges XML messages with third parties there are + times when you would like to validate the XML against a DTD that + is not available to the recipient of the message and so cannot be + referenced in the message itself. XMLUnit provides a + <literal>Validator</literal> class for this purpose.</para> + + <example><title>Validating Against a DTD</title> + <programlisting language="Java"><![CDATA[ +public void testValidation() throws Exception { + XMLUnit.getTestDocumentBuilderFactory().setValidating(true); + // As the document is parsed it is validated against its referenced DTD + Document myTestDocument = XMLUnit.buildTestDocument("..."); + String mySystemId = "..."; + String myDTDUrl = new File("...").toURL().toExternalForm(); + Validator myValidator = new Validator(myTestDocument, mySystemId, + myDTDUrl); + assertTrue("test document validates against unreferenced DTD", + myValidator.isValid()); +}]]></programlisting></example> + + </section> + + <section><title>Xpath Tests</title> + + <para>One of the strengths of XML is the ability to + programmatically extract specific parts of a document using XPath + expressions. The <literal>XMLTestCase</literal> class offers a + number of XPath related assertion methods, as demonstrated in this + test:</para> + + <example><title>Using Xpath Tests</title> + <programlisting language="Java"><![CDATA[ +public void testXPaths() throws Exception { + String mySolarSystemXML = "<solar-system>" + + "<planet name='Earth' position='3' supportsLife='yes'/>" + + "<planet name='Venus' position='4'/></solar-system>"; + assertXpathExists("//planet[@name='Earth']", mySolarSystemXML); + assertNotXpathExists("//star[@name='alpha centauri']", + mySolarSystemXML); + assertXpathsEqual("//planet[@name='Earth']", + "//planet[@position='3']", mySolarSystemXML); + assertXpathsNotEqual("//planet[@name='Venus']", + "//planet[@supportsLife='yes']", + mySolarSystemXML); +}]]></programlisting></example> + + <para>When an XPath expression is evaluated against a piece of XML + a <literal>NodeList</literal> is created that contains the + matching <literal>Node</literal>s. The methods in the previous + test <literal>assertXPathExists</literal>, + <literal>assertNotXPathExists</literal>, + <literal>assertXPathsEqual</literal>, and + <literal>assertXPathsNotEqual</literal> use these + <literal>NodeList</literal>s. However, the contents of a + <literal>NodeList</literal> can be flattened (or + <literal>String</literal>-ified) to a single value, and XMLUnit + also allows assertions to be made about this single value, as in + this test<footnote id="SimpleXpathEngine note"><para>Each of the + <literal>assertXpath...()</literal> methods uses the + <literal>SimpleXpathEngine</literal> class to evaluate an Xpath + expression.</para></footnote>:</para> + + <example><title>Testing Xpath Values</title> + <programlisting language="Java"><![CDATA[ +public void testXPathValues() throws Exception { + String myJavaFlavours = "<java-flavours>" + + "<jvm current='some platforms'>1.1.x</jvm>" + + "<jvm current='no'>1.2.x</jvm>" + + "<jvm current='yes'>1.3.x</jvm>" + + "<jvm current='yes' latest='yes'>1.4.x</jvm></javaflavours>"; + assertXpathEvaluatesTo("2", "count(//jvm[@current='yes'])", + myJavaFlavours); + assertXpathValuesEqual("//jvm[4]/@latest", "//jvm[4]/@current", + myJavaFlavours); + assertXpathValuesNotEqual("//jvm[2]/@current", + "//jvm[3]/@current", myJavaFlavours); +}]]></programlisting></example> + + <para>Xpaths are especially useful where a document is made up + largely of known, unchanging content with only a small amount of + changing content created by the system. One of the main areas + where constant "boilerplate" markup is combined with system + generated markup is of course in web applications. The power of + XPath expressions can make testing web page output quite trivial, + and XMLUnit supplies a means of converting even very badly formed + HTML into XML to aid this approach to testing.</para> + + <para>The <literal>HTMLDocumentBuilder</literal> class uses the + Swing HTML parser to convert marked-up content to Sax events. The + <literal>TolerantSaxDocumentBuilder</literal> class handles the + Sax events to build up a DOM document in a tolerant fashion + i.e. without mandating that opened elements are closed. (In a + purely XML world this class would have no purpose as there are + plenty of Sax event handlers that can build DOM documents from + well formed content). The test below illustrates how the use of + these classes:</para> + + <example><title>Working with non well-formed HTML</title> + <programlisting language="Java"><![CDATA[ +public void testXpathsInHTML() throws Exception { + String someBadlyFormedHTML = "<html><title>Ugh</title>" + + "<body><h1>Heading<ul>" + + "<li id='1'>Item One<li id='2'>Item Two"; + TolerantSaxDocumentBuilder tolerantSaxDocumentBuilder = + new TolerantSaxDocumentBuilder(XMLUnit.getTestParser()); + HTMLDocumentBuilder htmlDocumentBuilder = + new HTMLDocumentBuilder(tolerantSaxDocumentBuilder); + Document wellFormedDocument = + htmlDocumentBuilder.parse(someBadlyFormedHTML); + assertXpathEvaluatesTo("Item One", "/html/body//li[@id='1']", + wellFormedDocument); +}]]></programlisting></example> + + <para>One of the key points about using Xpaths with HTML content + is that extracting values in tests requires the values to be + identifiable. (This is just another way of saying that testing + HTML is easier when it is written to be testable.) In the previous + example id attributes were used to identify the list item values + that needed to be testable, however class attributes or span and + div tags can also be used to identify specific content for + testing.</para> + + </section> + + <section><title>Testing by Tree Walking</title> + + <para>The DOM specification allows a <literal>Document</literal> + to optionally implement the <literal>DocumentTraversal</literal> + interface. This interface allows an application to iterate over + the <literal>Node</literal>s contained in a + <literal>Document</literal>, or to "walk the DOM tree". The + XMLUnit <literal>NodeTest</literal> class and + <literal>NodeTester</literal> interface make use of + <literal>DocumentTraversal</literal> to expose individual + <literal>Node</literal>s in tests: the former handles the + mechanics of iteration, and the latter allows custom test + strategies to be implemented. A sample test strategy is supplied + by the <literal>CountingNodeTester</literal> class that counts the + nodes presented to it and compares the actual count to an expected + count. The test below illustrates its use:</para> + + <example><title>Using <literal>CountingNodeTester</literal></title> + <programlisting language="Java"><![CDATA[ +public void testCountingNodeTester() throws Exception { + String testXML = "<fibonacci><val>1</val><val>2</val><val>3</val>" + + "<val>5</val><val>9</val></fibonacci>"; + CountingNodeTester countingNodeTester = new CountingNodeTester(4); + assertNodeTestPasses(testXML, countingNodeTester, Node.TEXT_NODE); +}]]></programlisting></example> + + <para>This test fails as there are 5 text nodes, and JUnit + supplies the following message:</para> + + <programlisting> +Expected node test to pass, but it failed! Counted 5 node(s) but +expected 4 + </programlisting> + + <para>Note that if your DOM implementation does not support the + <literal>DocumentTraversal</literal> interface then XMLUnit will + throw an <literal>IllegalArgumentException</literal> informing you + that you cannot use the <literal>NodeTest</literal> or + <literal>NodeTester</literal> classes. Unfortunately even if your + DOM implementation does support + <literal>DocumentTraversal</literal>, attributes are not exposed + by iteration: however they can be examined from the + <literal>Element</literal> node that contains them.</para> + + <para>While the previous test could have been easily performed + using XPath, there are times when <literal>Node</literal> + iteration is more powerful. In general, this is true when there + are programmatic relationships between nodes that can be more + easily tested iteratively. The following test uses a custom + <literal>NodeTester</literal> class to illustrate the + potential:</para> + + <example><title>Using a Custom <literal>NodeTester</literal></title> + <programlisting language="Java"><![CDATA[ +public void testCustomNodeTester() throws Exception { + String testXML = "<fibonacci><val>1</val><val>2</val><val>3</val>" + + "<val>5</val><val>9</val></fibonacci>"; + NodeTest nodeTest = new NodeTest(testXML); + assertNodeTestPasses(nodeTest, new FibonacciNodeTester(), + new short[] {Node.TEXT_NODE, + Node.ELEMENT_NODE}, + true); +} + +private class FibonacciNodeTester extends AbstractNodeTester { + private int nextVal = 1, lastVal = 1, priorVal = 0; + + public void testText(Text text) throws NodeTestException { + int val = Integer.parseInt(text.getData()); + if (nextVal != val) { + throw new NodeTestException("Incorrect value", text); + } + nextVal = val + lastVal; + priorVal = lastVal; + lastVal = val; + } + + public void testElement(Element element) throws NodeTestException { + String name = element.getLocalName(); + if ("fibonacci".equals(name) || "val".equals(name)) { + return; + } + throw new NodeTestException("Unexpected element", element); + } + + public void noMoreNodes(NodeTest nodeTest) throws NodeTestException { + } +}]]></programlisting></example> + + <para>The test fails because the XML contains the wrong value for + the last number in the sequence:</para> + + <programlisting> +Expected node test to pass, but it failed! Incorrect value [#text: 9] + </programlisting> + + </section> +</article> Property changes on: trunk/xmlunit/src/site/XMLUnit-Java.xml ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-02-22 05:17:14
|
Revision: 148 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=148&view=rev Author: bodewig Date: 2007-02-21 21:17:08 -0800 (Wed, 21 Feb 2007) Log Message: ----------- Make XMLTestCase abstract Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java 2007-02-05 19:47:29 UTC (rev 147) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java 2007-02-22 05:17:08 UTC (rev 148) @@ -60,7 +60,7 @@ * @see Diff#identical() * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a> */ -public class XMLTestCase extends TestCase implements XSLTConstants { +public abstract class XMLTestCase extends TestCase implements XSLTConstants { /** * Construct a new XML test case. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2007-02-05 19:47:45
|
Revision: 147 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=147&view=rev Author: bodewig Date: 2007-02-05 11:47:29 -0800 (Mon, 05 Feb 2007) Log Message: ----------- Fix indentation and remove tabs: (defun fixup-file () (interactive) (save-excursion (let ((start (or (re-search-forward "package") (point-min)))) (indent-region start (point-max) nil) (untabify (point-min) (point-max))))) Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/AbstractNodeTester.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/CountingNodeTester.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/DetailedDiff.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Difference.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceConstants.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceEngine.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameQualifier.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementQualifier.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/HTMLDocumentBuilder.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/IgnoreTextAndAttributeValuesDifferenceListener.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeDescriptor.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeDetail.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeInputStream.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeTest.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/NodeTestException.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/SimpleXpathEngine.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/TolerantSaxDocumentBuilder.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Transform.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/Validator.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLAssert.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLTestCase.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XMLUnit.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/XpathNodeTracker.java trunk/xmlunit/src/java/org/custommonkey/xmlunit/examples/MultiLevelElementNameAndTextQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/Replacement.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/SimpleSerializer.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/examples/test_MultiLevelElementNameAndTextQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/jaxp13/test_Jaxp13XpathEngine.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_BugFixes.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Constants.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_CountingNodeTester.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DetailedDiff.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Diff.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Difference.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DifferenceEngine.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_DoctypeReader.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_ElementNameAndAttributeQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_ElementNameAndTextQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_ElementNameQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_HTMLDocumentBuilder.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_IgnoreTextAndAttributeValuesDifferenceListener.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_JAXP_1_2_Schema_Validation.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_NodeDescriptor.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_NodeTest.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Replacement.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_SimpleXpathEngine.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_TolerantSaxDocumentBuilder.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Transform.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_Validator.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_XMLTestCase.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_XMLUnit.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_XpathNodeTracker.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/AbstractNodeTester.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/AbstractNodeTester.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/AbstractNodeTester.java 2007-02-05 19:47:29 UTC (rev 147) @@ -71,41 +71,41 @@ */ public void testNode(Node aNode, NodeTest forTest) throws NodeTestException { switch (aNode.getNodeType()) { - case Node.ATTRIBUTE_NODE: - // should not happen as attributes are not exposed by DOM traversal - testAttribute((Attr)aNode); - break; - case Node.CDATA_SECTION_NODE: - testCDATASection((CDATASection)aNode); - break; - case Node.COMMENT_NODE: - testComment((Comment)aNode); - break; - case Node.DOCUMENT_TYPE_NODE: - testDocumentType((DocumentType)aNode); - break; - case Node.ELEMENT_NODE: - testElement((Element)aNode); - break; - case Node.ENTITY_NODE: - testEntity((Entity)aNode); - break; - case Node.ENTITY_REFERENCE_NODE: - testEntityReference((EntityReference)aNode); - break; - case Node.NOTATION_NODE: - testNotation((Notation)aNode); - break; - case Node.PROCESSING_INSTRUCTION_NODE: - testProcessingInstruction( - (ProcessingInstruction) aNode); - break; - case Node.TEXT_NODE: - testText((Text)aNode); - break; - default: - throw new NodeTestException("No delegate method for Node type", - aNode); + case Node.ATTRIBUTE_NODE: + // should not happen as attributes are not exposed by DOM traversal + testAttribute((Attr)aNode); + break; + case Node.CDATA_SECTION_NODE: + testCDATASection((CDATASection)aNode); + break; + case Node.COMMENT_NODE: + testComment((Comment)aNode); + break; + case Node.DOCUMENT_TYPE_NODE: + testDocumentType((DocumentType)aNode); + break; + case Node.ELEMENT_NODE: + testElement((Element)aNode); + break; + case Node.ENTITY_NODE: + testEntity((Entity)aNode); + break; + case Node.ENTITY_REFERENCE_NODE: + testEntityReference((EntityReference)aNode); + break; + case Node.NOTATION_NODE: + testNotation((Notation)aNode); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + testProcessingInstruction( + (ProcessingInstruction) aNode); + break; + case Node.TEXT_NODE: + testText((Text)aNode); + break; + default: + throw new NodeTestException("No delegate method for Node type", + aNode); } } @@ -191,7 +191,7 @@ } private void unhandled(Node aNode) throws NodeTestException { - throw new NodeTestException("Test fails by default in AbstractNodeTester", aNode); + throw new NodeTestException("Test fails by default in AbstractNodeTester", aNode); } /** @@ -201,7 +201,7 @@ * @exception NodeTestException if mode Nodes were expected */ public void noMoreNodes(NodeTest forTest) throws NodeTestException { - //by default do nothing + //by default do nothing } } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/CountingNodeTester.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/CountingNodeTester.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/CountingNodeTester.java 2007-02-05 19:47:29 UTC (rev 147) @@ -74,7 +74,7 @@ resetCounter(); if (testedNodes != expectedNumNodes) { throw new NodeTestException("Counted " + testedNodes - + " node(s) but expected " + expectedNumNodes); + + " node(s) but expected " + expectedNumNodes); } } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DetailedDiff.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DetailedDiff.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DetailedDiff.java 2007-02-05 19:47:29 UTC (rev 147) @@ -75,13 +75,13 @@ final int returnValue = super.differenceFound(difference); Difference localDifference = null; switch (returnValue) { - case RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL: - return returnValue; - case RETURN_ACCEPT_DIFFERENCE: - break; - case RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR: - difference.setRecoverable(true); - break; + case RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL: + return returnValue; + case RETURN_ACCEPT_DIFFERENCE: + break; + case RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR: + difference.setRecoverable(true); + break; } allDifferences.add(difference); return returnValue; Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Diff.java 2007-02-05 19:47:29 UTC (rev 147) @@ -72,7 +72,7 @@ * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a> */ public class Diff -implements DifferenceListener, ComparisonController { + implements DifferenceListener, ComparisonController { private final Document controlDoc; private final Document testDoc; private boolean similar = true; @@ -98,7 +98,7 @@ public Diff(Reader control, Reader test) throws SAXException, IOException { this(XMLUnit.buildDocument(XMLUnit.newControlParser(), control), - XMLUnit.buildDocument(XMLUnit.newTestParser(), test)); + XMLUnit.buildDocument(XMLUnit.newTestParser(), test)); } /** @@ -115,17 +115,17 @@ public Diff(String control, Transform testTransform) throws IOException, TransformerException, SAXException { this(XMLUnit.buildControlDocument(control), - testTransform.getResultDocument()); + testTransform.getResultDocument()); } - /** - * Construct a Diff that compares the XML read from two JAXP InputSources - */ + /** + * Construct a Diff that compares the XML read from two JAXP InputSources + */ public Diff(InputSource control, InputSource test) throws SAXException, IOException { - this(XMLUnit.buildDocument(XMLUnit.newControlParser(), control), - XMLUnit.buildDocument(XMLUnit.newTestParser(), test)); - } + this(XMLUnit.buildDocument(XMLUnit.newControlParser(), control), + XMLUnit.buildDocument(XMLUnit.newTestParser(), test)); + } /** * Construct a Diff that compares the XML in two JAXP DOMSources @@ -155,9 +155,9 @@ this.testDoc = getManipulatedDocument(testDoc); this.elementQualifierDelegate = elementQualifier; if (comparator == null) { - this.differenceEngine = new DifferenceEngine(this); + this.differenceEngine = new DifferenceEngine(this); } else { - this.differenceEngine = comparator; + this.differenceEngine = comparator; } this.messages = new StringBuffer(); } @@ -168,8 +168,8 @@ * @param prototype a prototypical instance */ protected Diff(Diff prototype) { - this(prototype.controlDoc, prototype.testDoc, prototype.differenceEngine, - prototype.elementQualifierDelegate); + this(prototype.controlDoc, prototype.testDoc, prototype.differenceEngine, + prototype.elementQualifierDelegate); } /** @@ -186,7 +186,7 @@ } try { Transform whitespaceStripper = XMLUnit.getStripWhitespaceTransform( - originalDoc); + originalDoc); return whitespaceStripper.getResultDocument(); } catch (TransformerException e) { throw new XMLUnitRuntimeException(e.getMessage(), e.getCause()); @@ -301,24 +301,24 @@ } switch (returnValue) { - case RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL: - return returnValue; - case RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR: - identical = false; + case RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL: + return returnValue; + case RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR: + identical = false; + haltComparison = false; + break; + case RETURN_ACCEPT_DIFFERENCE: + identical = false; + if (difference.isRecoverable()) { haltComparison = false; - break; - case RETURN_ACCEPT_DIFFERENCE: - identical = false; - if (difference.isRecoverable()) { - haltComparison = false; - } else { - similar = false; - haltComparison = true; - } - break; - default: - throw new IllegalArgumentException(returnValue - + " is not a defined DifferenceListener.RETURN_... value"); + } else { + similar = false; + haltComparison = true; + } + break; + default: + throw new IllegalArgumentException(returnValue + + " is not a defined DifferenceListener.RETURN_... value"); } if (haltComparison) { messages.append("\n[different]"); @@ -342,8 +342,8 @@ differenceListenerDelegate.skippedComparison(control, test); } else { System.err.println("DifferenceListener.skippedComparison: " - + "unhandled control node type=" + control - + ", unhandled test node type=" + test); + + "unhandled control node type=" + control + + ", unhandled test node type=" + test); } } @@ -392,13 +392,13 @@ this.differenceListenerDelegate = delegate; } - /** - * Override the <code>ElementQualifier</code> used to determine which - * control and test nodes are comparable for this difference comparison. - * @param delegate the ElementQualifier instance to delegate to. - */ - public void overrideElementQualifier(ElementQualifier delegate) { - this.elementQualifierDelegate = delegate; - } + /** + * Override the <code>ElementQualifier</code> used to determine which + * control and test nodes are comparable for this difference comparison. + * @param delegate the ElementQualifier instance to delegate to. + */ + public void overrideElementQualifier(ElementQualifier delegate) { + this.elementQualifierDelegate = delegate; + } } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/Difference.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/Difference.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/Difference.java 2007-02-05 19:47:29 UTC (rev 147) @@ -80,7 +80,7 @@ * encountered NodeDetails */ protected Difference(Difference prototype, NodeDetail controlNodeDetail, - NodeDetail testNodeDetail) { + NodeDetail testNodeDetail) { this(prototype.getId(), prototype.getDescription(), prototype.isRecoverable()); this.controlNodeDetail = controlNodeDetail; this.testNodeDetail = testNodeDetail; @@ -113,7 +113,7 @@ * a DetailedDiff. */ protected void setRecoverable(boolean overrideValue) { - recoverable = overrideValue; + recoverable = overrideValue; } /** @@ -121,7 +121,7 @@ * at the Node where this difference was encountered */ public NodeDetail getControlNodeDetail() { - return controlNodeDetail; + return controlNodeDetail; } /** @@ -129,7 +129,7 @@ * at the Node where this difference was encountered */ public NodeDetail getTestNodeDetail() { - return testNodeDetail; + return testNodeDetail; } /** @@ -153,22 +153,22 @@ * their details also */ public String toString() { - StringBuffer buf = new StringBuffer(); - if (controlNodeDetail == null || testNodeDetail == null) { - appendBasicRepresentation(buf); - } else { - appendDetailedRepresentation(buf); - } + StringBuffer buf = new StringBuffer(); + if (controlNodeDetail == null || testNodeDetail == null) { + appendBasicRepresentation(buf); + } else { + appendDetailedRepresentation(buf); + } return buf.toString(); } private void appendBasicRepresentation(StringBuffer buf) { buf.append("Difference (#").append(id). - append(") ").append(description); + append(") ").append(description); } private void appendDetailedRepresentation(StringBuffer buf) { - buf.append("Expected ").append(getDescription()) + buf.append("Expected ").append(getDescription()) .append(" '").append(controlNodeDetail.getValue()) .append("' but was '").append(testNodeDetail.getValue()) .append("' - comparing "); Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceConstants.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceConstants.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceConstants.java 2007-02-05 19:47:29 UTC (rev 147) @@ -42,53 +42,53 @@ * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a> */ public interface DifferenceConstants { - /** Comparing an implied attribute value against an explicit value */ - int ATTR_VALUE_EXPLICITLY_SPECIFIED_ID = 1; - /** Comparing 2 elements and one has an attribute the other does not */ - int ATTR_NAME_NOT_FOUND_ID = 2; - /** Comparing 2 attributes with the same name but different values */ - int ATTR_VALUE_ID = 3; - /** Comparing 2 attribute lists with the same attributes in different sequence */ - int ATTR_SEQUENCE_ID = 4; - /** Comparing 2 CDATA sections with different values */ - int CDATA_VALUE_ID = 5; - /** Comparing 2 comments with different values */ - int COMMENT_VALUE_ID = 6; - /** Comparing 2 document types with different names */ - int DOCTYPE_NAME_ID = 7; - /** Comparing 2 document types with different public identifiers */ - int DOCTYPE_PUBLIC_ID_ID = 8; - /** Comparing 2 document types with different system identifiers */ - int DOCTYPE_SYSTEM_ID_ID = 9; - /** Comparing 2 elements with different tag names */ - int ELEMENT_TAG_NAME_ID = 10; - /** Comparing 2 elements with different number of attributes */ - int ELEMENT_NUM_ATTRIBUTES_ID = 11; - /** Comparing 2 processing instructions with different targets */ - int PROCESSING_INSTRUCTION_TARGET_ID = 12; - /** Comparing 2 processing instructions with different instructions */ - int PROCESSING_INSTRUCTION_DATA_ID = 13; - /** Comparing 2 different text values */ - int TEXT_VALUE_ID = 14; - /** Comparing 2 nodes with different namespace prefixes */ - int NAMESPACE_PREFIX_ID = 15; - /** Comparing 2 nodes with different namespace URIs */ - int NAMESPACE_URI_ID = 16; - /** Comparing 2 nodes with different node types */ - int NODE_TYPE_ID = 17; - /** Comparing 2 nodes but only one has any children*/ - int HAS_CHILD_NODES_ID = 18; - /** Comparing 2 nodes with different numbers of children */ - int CHILD_NODELIST_LENGTH_ID = 19; - /** Comparing 2 nodes with children whose nodes are in different sequence*/ - int CHILD_NODELIST_SEQUENCE_ID = 20; - /** Comparing 2 Documents only one of which has a doctype */ - int HAS_DOCTYPE_DECLARATION_ID = 21; - /** Comparing an implied attribute value against an explicit value */ - public static final Difference ATTR_VALUE_EXPLICITLY_SPECIFIED = + int ATTR_VALUE_EXPLICITLY_SPECIFIED_ID = 1; + /** Comparing 2 elements and one has an attribute the other does not */ + int ATTR_NAME_NOT_FOUND_ID = 2; + /** Comparing 2 attributes with the same name but different values */ + int ATTR_VALUE_ID = 3; + /** Comparing 2 attribute lists with the same attributes in different sequence */ + int ATTR_SEQUENCE_ID = 4; + /** Comparing 2 CDATA sections with different values */ + int CDATA_VALUE_ID = 5; + /** Comparing 2 comments with different values */ + int COMMENT_VALUE_ID = 6; + /** Comparing 2 document types with different names */ + int DOCTYPE_NAME_ID = 7; + /** Comparing 2 document types with different public identifiers */ + int DOCTYPE_PUBLIC_ID_ID = 8; + /** Comparing 2 document types with different system identifiers */ + int DOCTYPE_SYSTEM_ID_ID = 9; + /** Comparing 2 elements with different tag names */ + int ELEMENT_TAG_NAME_ID = 10; + /** Comparing 2 elements with different number of attributes */ + int ELEMENT_NUM_ATTRIBUTES_ID = 11; + /** Comparing 2 processing instructions with different targets */ + int PROCESSING_INSTRUCTION_TARGET_ID = 12; + /** Comparing 2 processing instructions with different instructions */ + int PROCESSING_INSTRUCTION_DATA_ID = 13; + /** Comparing 2 different text values */ + int TEXT_VALUE_ID = 14; + /** Comparing 2 nodes with different namespace prefixes */ + int NAMESPACE_PREFIX_ID = 15; + /** Comparing 2 nodes with different namespace URIs */ + int NAMESPACE_URI_ID = 16; + /** Comparing 2 nodes with different node types */ + int NODE_TYPE_ID = 17; + /** Comparing 2 nodes but only one has any children*/ + int HAS_CHILD_NODES_ID = 18; + /** Comparing 2 nodes with different numbers of children */ + int CHILD_NODELIST_LENGTH_ID = 19; + /** Comparing 2 nodes with children whose nodes are in different sequence*/ + int CHILD_NODELIST_SEQUENCE_ID = 20; + /** Comparing 2 Documents only one of which has a doctype */ + int HAS_DOCTYPE_DECLARATION_ID = 21; + + /** Comparing an implied attribute value against an explicit value */ + public static final Difference ATTR_VALUE_EXPLICITLY_SPECIFIED = new Difference(ATTR_VALUE_EXPLICITLY_SPECIFIED_ID, - "attribute value explicitly specified", true); + "attribute value explicitly specified", true); /** Comparing 2 elements and one has an attribute the other does not */ public static final Difference ATTR_NAME_NOT_FOUND = @@ -133,12 +133,12 @@ /** Comparing 2 processing instructions with different targets */ public static final Difference PROCESSING_INSTRUCTION_TARGET = new Difference(PROCESSING_INSTRUCTION_TARGET_ID, - "processing instruction target"); + "processing instruction target"); /** Comparing 2 processing instructions with different instructions */ public static final Difference PROCESSING_INSTRUCTION_DATA = new Difference(PROCESSING_INSTRUCTION_DATA_ID, - "processing instruction data"); + "processing instruction data"); /** Comparing 2 different text values */ public static final Difference TEXT_VALUE = @@ -167,10 +167,10 @@ /** Comparing 2 nodes with children whose nodes are in different sequence*/ public static final Difference CHILD_NODELIST_SEQUENCE = new Difference(CHILD_NODELIST_SEQUENCE_ID, - "sequence of child nodes", true); + "sequence of child nodes", true); /** Comparing 2 Documents only one of which has a doctype */ public static final Difference HAS_DOCTYPE_DECLARATION = new Difference(HAS_DOCTYPE_DECLARATION_ID, - "presence of doctype declaration", true); + "presence of doctype declaration", true); } \ No newline at end of file Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceEngine.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceEngine.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DifferenceEngine.java 2007-02-05 19:47:29 UTC (rev 147) @@ -77,9 +77,9 @@ * @see ComparisonController#haltComparison(Difference) */ public DifferenceEngine(ComparisonController controller) { - this.controller = controller; - this.controlTracker = new XpathNodeTracker(); - this.testTracker = new XpathNodeTracker(); + this.controller = controller; + this.controlTracker = new XpathNodeTracker(); + this.testTracker = new XpathNodeTracker(); } /** @@ -93,21 +93,21 @@ * in any sequence and that sequence is not considered important. */ public void compare(Node control, Node test, DifferenceListener listener, - ElementQualifier elementQualifier) { - controlTracker.reset(); - testTracker.reset(); + ElementQualifier elementQualifier) { + controlTracker.reset(); + testTracker.reset(); try { compare(getNullOrNotNull(control), getNullOrNotNull(test), - control, test, listener, NODE_TYPE); + control, test, listener, NODE_TYPE); if (control!=null) { compareNode(control, test, listener, elementQualifier); } } catch (DifferenceFoundException e) { // thrown by the protected compare() method to terminate the // comparison and unwind the call stack back to here - } + } } - + private String getNullOrNotNull(Node aNode) { return aNode==null ? NULL_NODE : NOT_NULL_NODE; } @@ -122,41 +122,41 @@ * @throws DifferenceFoundException */ protected void compareNode(Node control, Node test, - DifferenceListener listener, ElementQualifier elementQualifier) - throws DifferenceFoundException { + DifferenceListener listener, ElementQualifier elementQualifier) + throws DifferenceFoundException { boolean comparable = compareNodeBasics(control, test, listener); boolean isDocumentNode = false; - if (comparable) { - switch (control.getNodeType()) { - case Node.ELEMENT_NODE: - compareElement((Element)control, (Element)test, listener); - break; - case Node.CDATA_SECTION_NODE: - case Node.TEXT_NODE: - compareText((CharacterData) control, - (CharacterData) test, listener); - break; - case Node.COMMENT_NODE: - compareComment((Comment)control, (Comment)test, listener); - break; - case Node.DOCUMENT_TYPE_NODE: - compareDocumentType((DocumentType)control, - (DocumentType)test, listener); - break; - case Node.PROCESSING_INSTRUCTION_NODE: - compareProcessingInstruction((ProcessingInstruction)control, - (ProcessingInstruction)test, listener); - break; - case Node.DOCUMENT_NODE: - isDocumentNode = true; - compareDocument((Document)control, (Document) test, - listener, elementQualifier); - break; - default: - listener.skippedComparison(control, test); - } - } + if (comparable) { + switch (control.getNodeType()) { + case Node.ELEMENT_NODE: + compareElement((Element)control, (Element)test, listener); + break; + case Node.CDATA_SECTION_NODE: + case Node.TEXT_NODE: + compareText((CharacterData) control, + (CharacterData) test, listener); + break; + case Node.COMMENT_NODE: + compareComment((Comment)control, (Comment)test, listener); + break; + case Node.DOCUMENT_TYPE_NODE: + compareDocumentType((DocumentType)control, + (DocumentType)test, listener); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + compareProcessingInstruction((ProcessingInstruction)control, + (ProcessingInstruction)test, listener); + break; + case Node.DOCUMENT_NODE: + isDocumentNode = true; + compareDocument((Document)control, (Document) test, + listener, elementQualifier); + break; + default: + listener.skippedComparison(control, test); + } + } compareHasChildNodes(control, test, listener); if (isDocumentNode) { @@ -166,8 +166,8 @@ compareNode(controlElement, testElement, listener, elementQualifier); } } else { - controlTracker.indent(); - testTracker.indent(); + controlTracker.indent(); + testTracker.indent(); compareNodeChildren(control, test, listener, elementQualifier); controlTracker.outdent(); testTracker.outdent(); @@ -183,14 +183,14 @@ * @throws DifferenceFoundException */ protected void compareDocument(Document control, Document test, - DifferenceListener listener, ElementQualifier elementQualifier) - throws DifferenceFoundException { + DifferenceListener listener, ElementQualifier elementQualifier) + throws DifferenceFoundException { DocumentType controlDoctype = control.getDoctype(); DocumentType testDoctype = test.getDoctype(); compare(getNullOrNotNull(controlDoctype), - getNullOrNotNull(testDoctype), - controlDoctype, testDoctype, listener, - HAS_DOCTYPE_DECLARATION); + getNullOrNotNull(testDoctype), + controlDoctype, testDoctype, listener, + HAS_DOCTYPE_DECLARATION); if (controlDoctype!=null && testDoctype!=null) { compareNode(controlDoctype, testDoctype, listener, elementQualifier); } @@ -206,7 +206,7 @@ * @throws DifferenceFoundException */ protected boolean compareNodeBasics(Node control, Node test, - DifferenceListener listener) throws DifferenceFoundException { + DifferenceListener listener) throws DifferenceFoundException { controlTracker.visited(control); testTracker.visited(test); @@ -220,9 +220,9 @@ NODE_TYPE); } compare(control.getNamespaceURI(), test.getNamespaceURI(), - control, test, listener, NAMESPACE_URI); + control, test, listener, NAMESPACE_URI); compare(control.getPrefix(), test.getPrefix(), - control, test, listener, NAMESPACE_PREFIX); + control, test, listener, NAMESPACE_PREFIX); return textAndCDATA || controlType.equals(testType); } @@ -245,13 +245,13 @@ * @throws DifferenceFoundException */ protected void compareHasChildNodes(Node control, Node test, - DifferenceListener listener) throws DifferenceFoundException { + DifferenceListener listener) throws DifferenceFoundException { Boolean controlHasChildren = control.hasChildNodes() ? Boolean.TRUE : Boolean.FALSE; Boolean testHasChildren = test.hasChildNodes() ? Boolean.TRUE : Boolean.FALSE; compare(controlHasChildren, testHasChildren, control, test, - listener, HAS_CHILD_NODES); + listener, HAS_CHILD_NODES); } /** @@ -264,8 +264,8 @@ * @throws DifferenceFoundException */ protected void compareNodeChildren(Node control, Node test, - DifferenceListener listener, ElementQualifier elementQualifier) - throws DifferenceFoundException { + DifferenceListener listener, ElementQualifier elementQualifier) + throws DifferenceFoundException { if (control.hasChildNodes() && test.hasChildNodes()) { NodeList controlChildren = control.getChildNodes(); NodeList testChildren = test.getChildNodes(); @@ -273,9 +273,9 @@ Integer controlLength = new Integer(controlChildren.getLength()); Integer testLength = new Integer(testChildren.getLength()); compare(controlLength, testLength, control, test, listener, - CHILD_NODELIST_LENGTH); + CHILD_NODELIST_LENGTH); compareNodeList(controlChildren, testChildren, - controlLength.intValue(), listener, elementQualifier); + controlLength.intValue(), listener, elementQualifier); } } @@ -397,80 +397,80 @@ * @throws DifferenceFoundException */ protected void compareElement(Element control, Element test, - DifferenceListener listener) throws DifferenceFoundException { - compare(getUnNamespacedNodeName(control), getUnNamespacedNodeName(test), - control, test, listener, ELEMENT_TAG_NAME); + DifferenceListener listener) throws DifferenceFoundException { + compare(getUnNamespacedNodeName(control), getUnNamespacedNodeName(test), + control, test, listener, ELEMENT_TAG_NAME); NamedNodeMap controlAttr = control.getAttributes(); - Integer controlNonXmlnsAttrLength = getNonXmlnsAttrLength(controlAttr); + Integer controlNonXmlnsAttrLength = getNonXmlnsAttrLength(controlAttr); NamedNodeMap testAttr = test.getAttributes(); Integer testNonXmlnsAttrLength = getNonXmlnsAttrLength(testAttr); compare(controlNonXmlnsAttrLength, testNonXmlnsAttrLength, - control, test, listener, ELEMENT_NUM_ATTRIBUTES); + control, test, listener, ELEMENT_NUM_ATTRIBUTES); compareElementAttributes(control, test, controlAttr, testAttr, - listener); + listener); } - private Integer getNonXmlnsAttrLength(NamedNodeMap attributes) { - int length = 0, maxLength = attributes.getLength(); - for (int i = 0; i < maxLength; ++i) { - if (!isXMLNSAttribute((Attr) attributes.item(i))) { - ++length; - } - } - return new Integer(length); - } + private Integer getNonXmlnsAttrLength(NamedNodeMap attributes) { + int length = 0, maxLength = attributes.getLength(); + for (int i = 0; i < maxLength; ++i) { + if (!isXMLNSAttribute((Attr) attributes.item(i))) { + ++length; + } + } + return new Integer(length); + } private void compareElementAttributes(Element control, Element test, - NamedNodeMap controlAttr, NamedNodeMap testAttr, - DifferenceListener listener) throws DifferenceFoundException { + NamedNodeMap controlAttr, NamedNodeMap testAttr, + DifferenceListener listener) throws DifferenceFoundException { for (int i=0; i < controlAttr.getLength(); ++i) { Attr nextAttr = (Attr) controlAttr.item(i); - if (isXMLNSAttribute(nextAttr)) { - // xml namespacing is handled in compareNodeBasics - } else { - boolean isNamespacedAttr = isNamespaced(nextAttr); - String attrName = getUnNamespacedNodeName(nextAttr, isNamespacedAttr); - Attr compareTo = null; - - if (isNamespacedAttr) { - compareTo = (Attr) testAttr.getNamedItemNS( - nextAttr.getNamespaceURI(), attrName); - } else { - compareTo = (Attr) testAttr.getNamedItem(attrName); - } - - if (compareTo != null) { - compareAttribute(nextAttr, compareTo, listener); - - Attr attributeItem = (Attr) testAttr.item(i); - String testAttrName = "[attribute absent]"; - if (attributeItem != null) { - testAttrName = getUnNamespacedNodeName(attributeItem); - } - compare(attrName, testAttrName, - nextAttr, compareTo, listener, ATTR_SEQUENCE); - } else { - compare(attrName, null, control, test, listener, - ATTR_NAME_NOT_FOUND); - } - } + if (isXMLNSAttribute(nextAttr)) { + // xml namespacing is handled in compareNodeBasics + } else { + boolean isNamespacedAttr = isNamespaced(nextAttr); + String attrName = getUnNamespacedNodeName(nextAttr, isNamespacedAttr); + Attr compareTo = null; + + if (isNamespacedAttr) { + compareTo = (Attr) testAttr.getNamedItemNS( + nextAttr.getNamespaceURI(), attrName); + } else { + compareTo = (Attr) testAttr.getNamedItem(attrName); + } + + if (compareTo != null) { + compareAttribute(nextAttr, compareTo, listener); + + Attr attributeItem = (Attr) testAttr.item(i); + String testAttrName = "[attribute absent]"; + if (attributeItem != null) { + testAttrName = getUnNamespacedNodeName(attributeItem); + } + compare(attrName, testAttrName, + nextAttr, compareTo, listener, ATTR_SEQUENCE); + } else { + compare(attrName, null, control, test, listener, + ATTR_NAME_NOT_FOUND); + } + } } controlTracker.clearTrackedAttribute(); testTracker.clearTrackedAttribute(); } private String getUnNamespacedNodeName(Node aNode) { - return getUnNamespacedNodeName(aNode, isNamespaced(aNode)); + return getUnNamespacedNodeName(aNode, isNamespaced(aNode)); } - private String getUnNamespacedNodeName(Node aNode, boolean isNamespacedNode) { - if (isNamespacedNode) { - return aNode.getLocalName(); - } - return aNode.getNodeName(); - } + private String getUnNamespacedNodeName(Node aNode, boolean isNamespacedNode) { + if (isNamespacedNode) { + return aNode.getLocalName(); + } + return aNode.getNodeName(); + } /** @@ -490,19 +490,19 @@ * @throws DifferenceFoundException */ protected void compareAttribute(Attr control, Attr test, - DifferenceListener listener) throws DifferenceFoundException { - controlTracker.visited(control); - testTracker.visited(test); - - compare(control.getPrefix(), test.getPrefix(), control, test, - listener, NAMESPACE_PREFIX); - + DifferenceListener listener) throws DifferenceFoundException { + controlTracker.visited(control); + testTracker.visited(test); + + compare(control.getPrefix(), test.getPrefix(), control, test, + listener, NAMESPACE_PREFIX); + compare(control.getValue(), test.getValue(), control, test, - listener, ATTR_VALUE); + listener, ATTR_VALUE); compare(control.getSpecified() ? Boolean.TRUE : Boolean.FALSE, - test.getSpecified() ? Boolean.TRUE : Boolean.FALSE, - control, test, listener, ATTR_VALUE_EXPLICITLY_SPECIFIED); + test.getSpecified() ? Boolean.TRUE : Boolean.FALSE, + control, test, listener, ATTR_VALUE_EXPLICITLY_SPECIFIED); } /** @@ -513,7 +513,7 @@ * @throws DifferenceFoundException */ protected void compareCDataSection(CDATASection control, CDATASection test, - DifferenceListener listener) throws DifferenceFoundException { + DifferenceListener listener) throws DifferenceFoundException { compareText(control, test, listener); } @@ -525,7 +525,7 @@ * @throws DifferenceFoundException */ protected void compareComment(Comment control, Comment test, - DifferenceListener listener) throws DifferenceFoundException { + DifferenceListener listener) throws DifferenceFoundException { compareCharacterData(control, test, listener, COMMENT_VALUE); } @@ -537,14 +537,14 @@ * @throws DifferenceFoundException */ protected void compareDocumentType(DocumentType control, DocumentType test, - DifferenceListener listener) throws DifferenceFoundException { + DifferenceListener listener) throws DifferenceFoundException { compare(control.getName(), test.getName(), control, test, listener, - DOCTYPE_NAME); + DOCTYPE_NAME); compare(control.getPublicId(), test.getPublicId(), control, test, listener, - DOCTYPE_PUBLIC_ID); + DOCTYPE_PUBLIC_ID); compare(control.getSystemId(), test.getSystemId(), - control, test, listener, DOCTYPE_SYSTEM_ID); + control, test, listener, DOCTYPE_SYSTEM_ID); } /** @@ -555,12 +555,12 @@ * @throws DifferenceFoundException */ protected void compareProcessingInstruction(ProcessingInstruction control, - ProcessingInstruction test, DifferenceListener listener) - throws DifferenceFoundException { + ProcessingInstruction test, DifferenceListener listener) + throws DifferenceFoundException { compare(control.getTarget(), test.getTarget(), control, test, listener, - PROCESSING_INSTRUCTION_TARGET); + PROCESSING_INSTRUCTION_TARGET); compare(control.getData(), test.getData(), control, test, listener, - PROCESSING_INSTRUCTION_DATA); + PROCESSING_INSTRUCTION_DATA); } /** @@ -599,10 +599,10 @@ * @throws DifferenceFoundException */ private void compareCharacterData(CharacterData control, CharacterData test, - DifferenceListener listener, Difference difference) - throws DifferenceFoundException { + DifferenceListener listener, Difference difference) + throws DifferenceFoundException { compare(control.getData(), test.getData(), control, test, listener, - difference); + difference); } /** @@ -617,15 +617,15 @@ * @throws DifferenceFoundException */ protected void compare(Object expected, Object actual, - Node control, Node test, DifferenceListener listener, Difference difference) - throws DifferenceFoundException { + Node control, Node test, DifferenceListener listener, Difference difference) + throws DifferenceFoundException { if (unequal(expected, actual)) { - NodeDetail controlDetail = new NodeDetail(String.valueOf(expected), - control, controlTracker.toXpathString()); - NodeDetail testDetail = new NodeDetail(String.valueOf(actual), - test, testTracker.toXpathString()); - Difference differenceInstance = new Difference(difference, - controlDetail, testDetail); + NodeDetail controlDetail = new NodeDetail(String.valueOf(expected), + control, controlTracker.toXpathString()); + NodeDetail testDetail = new NodeDetail(String.valueOf(actual), + test, testTracker.toXpathString()); + Difference differenceInstance = new Difference(difference, + controlDetail, testDetail); listener.differenceFound(differenceInstance); if (controller.haltComparison(differenceInstance)) { throw flowControlException; Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/DoctypeReader.java 2007-02-05 19:47:29 UTC (rev 147) @@ -72,7 +72,7 @@ * @param systemID */ public DoctypeReader(Reader originalSource, String doctypeName, - String systemID) { + String systemID) { this.originalSource = originalSource; this.doctypeName = doctypeName; this.systemId = systemID; @@ -132,13 +132,13 @@ curChar = withinContent.charAt(i); if (curChar == '<') { switch (withinContent.charAt(i + 1)) { - case '?': - case '!': - case '-': - canInsert = false; - break; - default: - startAt = i; + case '?': + case '!': + case '-': + canInsert = false; + break; + default: + startAt = i; } } else if (curChar == '>') { canInsert = true; @@ -157,7 +157,7 @@ * @return the content, after DOCTYPE amendment / addition */ public String replaceDoctype(StringBuffer withinContent, - String doctypeName, String systemId) { + String doctypeName, String systemId) { String content = withinContent.toString(); int startDoctype = content.indexOf(DOCTYPE); boolean noCurrentDoctype = false; @@ -206,7 +206,7 @@ private Reader getReplacementReader() throws IOException { StringBuffer originalContent = getContent(originalSource); String replacedContent = replaceDoctype(originalContent, - doctypeName, systemId); + doctypeName, systemId); return new StringReader(replacedContent); } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java 2007-02-05 19:47:29 UTC (rev 147) @@ -7,16 +7,16 @@ modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of the xmlunit.sourceforge.net nor the names - of its contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -49,105 +49,105 @@ * @see Diff#overrideElementQualifier(ElementQualifier) */ public class ElementNameAndAttributeQualifier extends ElementNameQualifier { - public static final String[] ALL_ATTRIBUTES = {"*"}; - - private final String[] qualifyingAttrNames; - - /** - * No-args constructor: use all attributes from all elements to determine - * whether elements qualify for comparability - */ - public ElementNameAndAttributeQualifier() { - this(ALL_ATTRIBUTES); - } - - /** - * Simple constructor for a single qualifying attribute name - * @param attrName the value to use to qualify whether two elements can be - * compared further for differences - */ - public ElementNameAndAttributeQualifier(String attrName) { - this(new String[] {attrName}); - } + public static final String[] ALL_ATTRIBUTES = {"*"}; + + private final String[] qualifyingAttrNames; + + /** + * No-args constructor: use all attributes from all elements to determine + * whether elements qualify for comparability + */ + public ElementNameAndAttributeQualifier() { + this(ALL_ATTRIBUTES); + } + + /** + * Simple constructor for a single qualifying attribute name + * @param attrName the value to use to qualify whether two elements can be + * compared further for differences + */ + public ElementNameAndAttributeQualifier(String attrName) { + this(new String[] {attrName}); + } - /** - * Extended constructor for multiple qualifying attribute names - * @param attrNames the array of values to use to qualify whether two - * elements can be compared further for differences - */ - public ElementNameAndAttributeQualifier(String[] attrNames) { - this.qualifyingAttrNames = attrNames; - } + /** + * Extended constructor for multiple qualifying attribute names + * @param attrNames the array of values to use to qualify whether two + * elements can be compared further for differences + */ + public ElementNameAndAttributeQualifier(String[] attrNames) { + this.qualifyingAttrNames = attrNames; + } - /** - * Determine whether two elements qualify for further Difference comparison. - * @param differenceEngine the DifferenceEngine instance wanting to - * determine if the elements are comparable - * @param control - * @param test - * @return true if the two elements qualify for further comparison based on - * both the superclass qualification (namespace URI and non- namespaced tag - * name), and the presence of qualifying attributes with the same values; - * false otherwise - */ - public boolean qualifyForComparison(Element control, Element test) { - if (super.qualifyForComparison(control, test)) { - return areAttributesComparable(control, test); - } - return false; - } - - /** - * Determine whether the qualifying attributes are present in both elements - * and if so whether their values are the same - * @param control - * @param test - * @return true if all qualifying attributes are present with the same - * values, false otherwise - */ - protected boolean areAttributesComparable(Element control, Element test) { - String controlValue, testValue; - Attr[] qualifyingAttributes; - NamedNodeMap namedNodeMap = control.getAttributes(); - if (qualifyingAttrNames == ALL_ATTRIBUTES) { - qualifyingAttributes = new Attr[namedNodeMap.getLength()]; - for (int n=0; n < qualifyingAttributes.length; ++n) { - qualifyingAttributes[n] = (Attr) namedNodeMap.item(n); - } - } else { - qualifyingAttributes = new Attr[qualifyingAttrNames.length]; - for (int n=0; n < qualifyingAttrNames.length; ++n) { - qualifyingAttributes[n] = (Attr) namedNodeMap.getNamedItem(qualifyingAttrNames[n]); - } - } - - String nsURI, name; - for (int i=0; i < qualifyingAttributes.length; ++i) { - if (qualifyingAttributes[i] != null) { - nsURI = qualifyingAttributes[i].getNamespaceURI(); - controlValue = qualifyingAttributes[i].getNodeValue(); - name = qualifyingAttributes[i].getName(); - } else { - // cannot be "*" case - nsURI = controlValue = ""; - name = qualifyingAttrNames[i]; - } - if (nsURI == null || nsURI.length() == 0) { - testValue = test.getAttribute(name); - } else { - testValue = test.getAttributeNS(nsURI, qualifyingAttributes[i].getLocalName()); - } - if (controlValue == null) { - if (testValue != null) { - return false; - } - } else { - if (!controlValue.equals(testValue)) { - return false; - } - } - } - return true; - } + /** + * Determine whether two elements qualify for further Difference comparison. + * @param differenceEngine the DifferenceEngine instance wanting to + * determine if the elements are comparable + * @param control + * @param test + * @return true if the two elements qualify for further comparison based on + * both the superclass qualification (namespace URI and non- namespaced tag + * name), and the presence of qualifying attributes with the same values; + * false otherwise + */ + public boolean qualifyForComparison(Element control, Element test) { + if (super.qualifyForComparison(control, test)) { + return areAttributesComparable(control, test); + } + return false; + } + + /** + * Determine whether the qualifying attributes are present in both elements + * and if so whether their values are the same + * @param control + * @param test + * @return true if all qualifying attributes are present with the same + * values, false otherwise + */ + protected boolean areAttributesComparable(Element control, Element test) { + String controlValue, testValue; + Attr[] qualifyingAttributes; + NamedNodeMap namedNodeMap = control.getAttributes(); + if (qualifyingAttrNames == ALL_ATTRIBUTES) { + qualifyingAttributes = new Attr[namedNodeMap.getLength()]; + for (int n=0; n < qualifyingAttributes.length; ++n) { + qualifyingAttributes[n] = (Attr) namedNodeMap.item(n); + } + } else { + qualifyingAttributes = new Attr[qualifyingAttrNames.length]; + for (int n=0; n < qualifyingAttrNames.length; ++n) { + qualifyingAttributes[n] = (Attr) namedNodeMap.getNamedItem(qualifyingAttrNames[n]); + } + } + + String nsURI, name; + for (int i=0; i < qualifyingAttributes.length; ++i) { + if (qualifyingAttributes[i] != null) { + nsURI = qualifyingAttributes[i].getNamespaceURI(); + controlValue = qualifyingAttributes[i].getNodeValue(); + name = qualifyingAttributes[i].getName(); + } else { + // cannot be "*" case + nsURI = controlValue = ""; + name = qualifyingAttrNames[i]; + } + if (nsURI == null || nsURI.length() == 0) { + testValue = test.getAttribute(name); + } else { + testValue = test.getAttributeNS(nsURI, qualifyingAttributes[i].getLocalName()); + } + if (controlValue == null) { + if (testValue != null) { + return false; + } + } else { + if (!controlValue.equals(testValue)) { + return false; + } + } + } + return true; + } } Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java 2007-02-02 21:36:23 UTC (rev 146) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java 2007-02-05 19:47:29 UTC (rev 147) @@ -7,16 +7,16 @@ modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of the xmlunit.sourceforge.net nor the names - of its contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -50,53 +50,53 @@ * @see Diff#overrideElementQualifier(ElementQualifier) */ public class ElementNameAndTextQualifier extends ElementNameQualifier { - /** - * Determine whether two elements qualify for further Difference comparison. - * @param control - * @param test - * @return true if the two elements qualify for further comparison based on - * both the superclass qualification (namespace URI and non- namespaced tag - * name), and the qualification of the text nodes contained within the - * elements; false otherwise - */ - public bo... [truncated message content] |
From: <bo...@us...> - 2007-02-02 21:36:25
|
Revision: 146 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=146&view=rev Author: bodewig Date: 2007-02-02 13:36:23 -0800 (Fri, 02 Feb 2007) Log Message: ----------- Move MultiLevelElementNameAndTextQualifier to examples package Added Paths: ----------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/examples/MultiLevelElementNameAndTextQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/examples/test_MultiLevelElementNameAndTextQualifier.java Removed Paths: ------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/MultiLevelElementNameAndTextQualifier.java trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_MultiLevelElementNameAndTextQualifier.java Deleted: trunk/xmlunit/src/java/org/custommonkey/xmlunit/MultiLevelElementNameAndTextQualifier.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/MultiLevelElementNameAndTextQualifier.java 2007-02-02 20:44:21 UTC (rev 145) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/MultiLevelElementNameAndTextQualifier.java 2007-02-02 21:36:23 UTC (rev 146) @@ -1,117 +0,0 @@ -/* -****************************************************************** -Copyright (c) 2001, Jeff Martin, Tim Bacon -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of the xmlunit.sourceforge.net nor the names - of its contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -****************************************************************** -*/ - -package org.custommonkey.xmlunit; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -/** - * Per popular request an interface implementation that uses element - * names and the text node containes in the n'th child node to compare - * elements. - * - * <p>This means {@link ElementNameAndTextQualifier - * ElementNameQualifier} and MultiLevelElementNameQualifier(1) should - * lead to the same results.</p> - * - * <p>Any attribute values ar completely ignored. Only works on - * elements with exactly one child element at each level.</p> - * - * <p>This class mostly exists as an example for custom ElementQualifiers.</p> - */ -public class MultiLevelElementNameAndTextQualifier - implements ElementQualifier { - - private final int levels; - - private static final ElementNameQualifier NAME_QUALIFIER = - new ElementNameQualifier(); - private static final ElementNameAndTextQualifier NAME_AND_TEXT_QUALIFIER = - new ElementNameAndTextQualifier(); - - /** - * Uses element names and the text nested <code>levels</code> - * child elements deeper into the element to compare elements. - */ - public MultiLevelElementNameAndTextQualifier(int levels) { - if (levels < 1) { - throw new IllegalArgumentException("levels must be equal or" - + " greater than one"); - } - this.levels = levels; - } - - public boolean qualifyForComparison(Element control, Element test) { - boolean stillSimilar = true; - Element currentControl = control; - Element currentTest = test; - - // match on element names only for leading levels - for (int currentLevel = 0; stillSimilar && currentLevel <= levels - 2; - currentLevel++) { - stillSimilar = NAME_QUALIFIER.qualifyForComparison(currentControl, - currentTest); - if (stillSimilar) { - if (currentControl.hasChildNodes() - && currentTest.hasChildNodes()) { - Node n1 = currentControl.getFirstChild(); - Node n2 = currentTest.getFirstChild(); - if (n1.getNodeType() == Node.ELEMENT_NODE - && n2.getNodeType() == Node.ELEMENT_NODE) { - currentControl = (Element) n1; - currentTest = (Element) n2; - } else { - stillSimilar = false; - } - } else { - stillSimilar = false; - } - } - } - - // finally compare the level containing the text child node - if (stillSimilar) { - stillSimilar = NAME_AND_TEXT_QUALIFIER - .qualifyForComparison(currentControl, currentTest); - } - - return stillSimilar; - } - -} Copied: trunk/xmlunit/src/java/org/custommonkey/xmlunit/examples/MultiLevelElementNameAndTextQualifier.java (from rev 144, trunk/xmlunit/src/java/org/custommonkey/xmlunit/MultiLevelElementNameAndTextQualifier.java) =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/examples/MultiLevelElementNameAndTextQualifier.java (rev 0) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/examples/MultiLevelElementNameAndTextQualifier.java 2007-02-02 21:36:23 UTC (rev 146) @@ -0,0 +1,121 @@ +/* +****************************************************************** +Copyright (c) 2001, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + +package org.custommonkey.xmlunit.examples; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import org.custommonkey.xmlunit.ElementNameAndTextQualifier; +import org.custommonkey.xmlunit.ElementNameQualifier; +import org.custommonkey.xmlunit.ElementQualifier; + +/** + * Per popular request an interface implementation that uses element + * names and the text node containes in the n'th child node to compare + * elements. + * + * <p>This means {@link ElementNameAndTextQualifier + * ElementNameQualifier} and MultiLevelElementNameQualifier(1) should + * lead to the same results.</p> + * + * <p>Any attribute values ar completely ignored. Only works on + * elements with exactly one child element at each level.</p> + * + * <p>This class mostly exists as an example for custom ElementQualifiers.</p> + */ +public class MultiLevelElementNameAndTextQualifier + implements ElementQualifier { + + private final int levels; + + private static final ElementNameQualifier NAME_QUALIFIER = + new ElementNameQualifier(); + private static final ElementNameAndTextQualifier NAME_AND_TEXT_QUALIFIER = + new ElementNameAndTextQualifier(); + + /** + * Uses element names and the text nested <code>levels</code> + * child elements deeper into the element to compare elements. + */ + public MultiLevelElementNameAndTextQualifier(int levels) { + if (levels < 1) { + throw new IllegalArgumentException("levels must be equal or" + + " greater than one"); + } + this.levels = levels; + } + + public boolean qualifyForComparison(Element control, Element test) { + boolean stillSimilar = true; + Element currentControl = control; + Element currentTest = test; + + // match on element names only for leading levels + for (int currentLevel = 0; stillSimilar && currentLevel <= levels - 2; + currentLevel++) { + stillSimilar = NAME_QUALIFIER.qualifyForComparison(currentControl, + currentTest); + if (stillSimilar) { + if (currentControl.hasChildNodes() + && currentTest.hasChildNodes()) { + Node n1 = currentControl.getFirstChild(); + Node n2 = currentTest.getFirstChild(); + if (n1.getNodeType() == Node.ELEMENT_NODE + && n2.getNodeType() == Node.ELEMENT_NODE) { + currentControl = (Element) n1; + currentTest = (Element) n2; + } else { + stillSimilar = false; + } + } else { + stillSimilar = false; + } + } + } + + // finally compare the level containing the text child node + if (stillSimilar) { + stillSimilar = NAME_AND_TEXT_QUALIFIER + .qualifyForComparison(currentControl, currentTest); + } + + return stillSimilar; + } + +} Copied: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/examples/test_MultiLevelElementNameAndTextQualifier.java (from rev 144, trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_MultiLevelElementNameAndTextQualifier.java) =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/examples/test_MultiLevelElementNameAndTextQualifier.java (rev 0) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/examples/test_MultiLevelElementNameAndTextQualifier.java 2007-02-02 21:36:23 UTC (rev 146) @@ -0,0 +1,147 @@ +/* +****************************************************************** +Copyright (c) 2001, Jeff Martin, Tim Bacon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the xmlunit.sourceforge.net nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +****************************************************************** +*/ + +package org.custommonkey.xmlunit.examples; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.ElementNameAndTextQualifier; +import org.custommonkey.xmlunit.ElementQualifier; +import org.custommonkey.xmlunit.XMLUnit; + +/** + * JUnit testcase for MultiLevelElementNameAndTextQualifier + * @see test_Diff#testRepeatedElementNamesWithTextQualification() + */ +public class test_MultiLevelElementNameAndTextQualifier extends TestCase { + private static final String TAG_NAME = "tagYoureIt"; + private static final String TAG_NAME2 = "tagYoureIt2"; + private static final String TEXT_A = "textA"; + private static final String TEXT_B = "textB"; + private Document document; + + // copy of ElementNameAndTextQualifier test + public void testSingleTextValue() throws Exception { + ElementQualifier qualifier = + new MultiLevelElementNameAndTextQualifier(1); + + Element control = document.createElement(TAG_NAME); + control.appendChild(document.createTextNode(TEXT_A)); + + Element test = document.createElement(TAG_NAME); + + assertFalse("control text not comparable to empty text", + qualifier.qualifyForComparison(control, test)); + + test.appendChild(document.createTextNode(TEXT_A)); + assertTrue("control textA comparable to test textA", + qualifier.qualifyForComparison(control, test)); + + test = document.createElement(TAG_NAME); + + test.appendChild(document.createTextNode(TEXT_B)); + assertFalse("control textA not comparable to test textB", + qualifier.qualifyForComparison(control, test)); + } + + // copy of ElementNameAndTextQualifier test + public void testMultipleTextValues() throws Exception { + ElementQualifier qualifier = + new MultiLevelElementNameAndTextQualifier(1); + + Element control = document.createElement(TAG_NAME); + control.appendChild(document.createTextNode(TEXT_A)); + control.appendChild(document.createTextNode(TEXT_B)); + + Element test = document.createElement(TAG_NAME); + test.appendChild(document.createTextNode(TEXT_A + TEXT_B)); + assertTrue("denormalised control text comparable to normalised test text", + qualifier.qualifyForComparison(control, test)); + } + + // three levels + public void testThreeLevels() throws Exception { + ElementQualifier qualifier = + new MultiLevelElementNameAndTextQualifier(3); + + Element control = document.createElement(TAG_NAME); + Element child = document.createElement(TAG_NAME2); + control.appendChild(child); + Element child2 = document.createElement(TAG_NAME); + child.appendChild(child2); + child2.appendChild(document.createTextNode(TEXT_B)); + + Element test = document.createElement(TAG_NAME); + child = document.createElement(TAG_NAME2); + test.appendChild(child); + child2 = document.createElement(TAG_NAME); + child.appendChild(child2); + child2.appendChild(document.createTextNode(TEXT_B)); + + assertTrue(qualifier.qualifyForComparison(control, test)); + } + + /** + * @see https://sourceforge.net/forum/forum.php?thread_id=1440169&forum_id=73274 + */ + public void testThread1440169() throws Exception { + String s1 = "<a><b><c>foo</c></b><b><c>bar</c></b></a>"; + String s2 = "<a><b><c>bar</c></b><b><c>foo</c></b></a>"; + Diff d = new Diff(s1, s2); + assertFalse(d.similar()); + + // reset + d = new Diff(s1, s2); + d.overrideElementQualifier(new ElementNameAndTextQualifier()); + assertFalse(d.similar()); + + // reset once again + d = new Diff(s1, s2); + d.overrideElementQualifier(new MultiLevelElementNameAndTextQualifier(2)); + assertTrue(d.similar()); + + } + + public void setUp() throws Exception { + document = XMLUnit.newControlParser().newDocument(); + } + +} Deleted: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_MultiLevelElementNameAndTextQualifier.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_MultiLevelElementNameAndTextQualifier.java 2007-02-02 20:44:21 UTC (rev 145) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/test_MultiLevelElementNameAndTextQualifier.java 2007-02-02 21:36:23 UTC (rev 146) @@ -1,142 +0,0 @@ -/* -****************************************************************** -Copyright (c) 2001, Jeff Martin, Tim Bacon -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of the xmlunit.sourceforge.net nor the names - of its contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -****************************************************************** -*/ - -package org.custommonkey.xmlunit; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * JUnit testcase for MultiLevelElementNameAndTextQualifier - * @see test_Diff#testRepeatedElementNamesWithTextQualification() - */ -public class test_MultiLevelElementNameAndTextQualifier extends TestCase { - private static final String TAG_NAME = "tagYoureIt"; - private static final String TAG_NAME2 = "tagYoureIt2"; - private static final String TEXT_A = "textA"; - private static final String TEXT_B = "textB"; - private Document document; - - // copy of ElementNameAndTextQualifier test - public void testSingleTextValue() throws Exception { - ElementQualifier qualifier = - new MultiLevelElementNameAndTextQualifier(1); - - Element control = document.createElement(TAG_NAME); - control.appendChild(document.createTextNode(TEXT_A)); - - Element test = document.createElement(TAG_NAME); - - assertFalse("control text not comparable to empty text", - qualifier.qualifyForComparison(control, test)); - - test.appendChild(document.createTextNode(TEXT_A)); - assertTrue("control textA comparable to test textA", - qualifier.qualifyForComparison(control, test)); - - test = document.createElement(TAG_NAME); - - test.appendChild(document.createTextNode(TEXT_B)); - assertFalse("control textA not comparable to test textB", - qualifier.qualifyForComparison(control, test)); - } - - // copy of ElementNameAndTextQualifier test - public void testMultipleTextValues() throws Exception { - ElementQualifier qualifier = - new MultiLevelElementNameAndTextQualifier(1); - - Element control = document.createElement(TAG_NAME); - control.appendChild(document.createTextNode(TEXT_A)); - control.appendChild(document.createTextNode(TEXT_B)); - - Element test = document.createElement(TAG_NAME); - test.appendChild(document.createTextNode(TEXT_A + TEXT_B)); - assertTrue("denormalised control text comparable to normalised test text", - qualifier.qualifyForComparison(control, test)); - } - - // three levels - public void testThreeLevels() throws Exception { - ElementQualifier qualifier = - new MultiLevelElementNameAndTextQualifier(3); - - Element control = document.createElement(TAG_NAME); - Element child = document.createElement(TAG_NAME2); - control.appendChild(child); - Element child2 = document.createElement(TAG_NAME); - child.appendChild(child2); - child2.appendChild(document.createTextNode(TEXT_B)); - - Element test = document.createElement(TAG_NAME); - child = document.createElement(TAG_NAME2); - test.appendChild(child); - child2 = document.createElement(TAG_NAME); - child.appendChild(child2); - child2.appendChild(document.createTextNode(TEXT_B)); - - assertTrue(qualifier.qualifyForComparison(control, test)); - } - - /** - * @see https://sourceforge.net/forum/forum.php?thread_id=1440169&forum_id=73274 - */ - public void testThread1440169() throws Exception { - String s1 = "<a><b><c>foo</c></b><b><c>bar</c></b></a>"; - String s2 = "<a><b><c>bar</c></b><b><c>foo</c></b></a>"; - Diff d = new Diff(s1, s2); - assertFalse(d.similar()); - - // reset - d = new Diff(s1, s2); - d.overrideElementQualifier(new ElementNameAndTextQualifier()); - assertFalse(d.similar()); - - // reset once again - d = new Diff(s1, s2); - d.overrideElementQualifier(new MultiLevelElementNameAndTextQualifier(2)); - assertTrue(d.similar()); - - } - - public void setUp() throws Exception { - document = XMLUnit.newControlParser().newDocument(); - } - -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |