Java & XML, 2nd Edition by Brett Mclaughlin The unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification This page was updated January 20, 2004. UNCONFIRMED errors and comments from readers: (Example zip files) both total and individual zip files at newInstance.com; The zipped example files have case inconsistency in the chapter numbering. Namely Ch02/ Ch06/ Ch07/ Ch10/ Ch11/ Ch12/ Ch13/ Ch15 but ch03/ ch04/ ch05/ ch08/ ch09/ This is a sufficient inconvenience in a case-sensitive file system to motivate a user to change them, but of course updates might have the same error... I prefer Ch to ch (5) 1st paragraph; The last sentence "You can ... about data biding in Chapter 14." should end with "... Chapter 15." {7} list, last item; "Microsoft's MXSML [sic!] Parser [...]" ---> Must be "MSXML" {22} The Example 2.3 DTD; In the DTD, should be since in the contents.xml, chapter has an attribute called "label" and not "number". (36) 2nd paragraph; The sentence: "Notice the rather odd code fragment ..." T he second should be a closing tag: . That matches with th e referenced code on the previous page. {36} 2nd paragraph, 3rd sentence; instead of 'Notice the rather odd ... This construct generates a space between the word "Chapter" and the chapter number (there is a single space ...' it should be 'Notice the rather odd ... This construct generates a space between the dot after chapter number and the chapter title (there is a single space ...' [43] in the buildTree() method; // Register content handler // Register error // Parse should be: // Register content handler reader.setContentHandler(jTreeContentHandler); // Register error handler reader.setErrorHandler(jTreeErrorHandler); // Parse InputSource inputSource = new InputSource(xmlURI); reader.parse(inputSource); {44} U-R-What? block; URI stands for "uniform resource identifier", not "uniform resource indicator". In other words not "indicator" but "identifier". {46} line 3: running the first SAX example; No error, just a comment. You recommend the "contents.xml"-File here. But you don't give any hint that this is already a very specialized XML-file for which the parser has to look up one or more URL's on the internet for the namespace definitions. I experienced the examples you provide won't work if 1) there's no connection to the internet 2) if you don't set the proxy settings if behind a firewall, e.g. if you didn't think about using the -Dhttp.proxyHost and the -Dttp.proxyPort option when running the example. You should at least place a comment here for the users trying your xml examples the first time. I guess there'll be a lot of readers running into the same problem, then puzzling over the correct XML URI and wondering why they get a NoRouteToHost- Exception. {47-48} 47: last paragraph, 48: first line of code; You refer to the setSystemId() method as setSystemID() (note the capital "D" in "ID"), which at least where the very latest Xerces parser is concerned throws a complier error. {48} first line of top code listing; Wrong method name. The line should be changed from inputSource.setSystemID(xmlURI); to inputSource.setSystemId(xmlURI); [57] When processing attributes, the attribute prefix is never found in the mapings. Change: String attPrefix = (String)namespaceMappings.get(namespaceURI); to: String attPrefix = (String)namespaceMappings.get(attURI); {68} changing DTD to causes a fatal error....not a non fatal error [77] Code listing in middle of page; Here you say that intentionally change "book" in the doctype declaration to "Book" to provoke an error (because XML is case-sensitive). But its written as "Book" before (on page 69) and so there would have been a parse error there already (81) 2nd paragraph; The URL listed for information on the SAX defined features should be http://xml.apache.org/xerces2-j/features.html not http://xml.apache.org/xerces2-j/properties.html (81) 1st paragraph; "The two standard SAX properties..." should be: "These two standard SAX properties..." (Change "The" to "These".) [83 - 101] signature of JTreeContentHandler constructor; From page 83 on for the rest of chapter 4 the signature of the JTreeContentHandler constructor in the code samples is always extended by the parameter "reader" although no change has been done to the class since it was last quoted without the additional parameter on page 79. [92] Figure The diagram on page 92 shows output (i.e. the DTD and Comment nodes) that cannot be generated by code provided up to that point in the book. It is finally explained 3 pages later. [93] code at bottom of page; Putting the XMLWriter between the XMLReader and the NamespaceFilter prevents the writer from seeing the changes made by the filter. The constructor for the JTreeContentHandler suddenly (with no explanation in the text) needs three arguments, so that it can maintain a reference to the XMLReader. However that reference to the XMLReader is never actually used. [93] penultimate sentence before code sample; "add import statements for java.io.Writer" should be changed to "add import statements for java.io.FileWriter" {95-98} all; What is presented regarding the LexicalHandler is correct, but there is an omission, failing to say that the lexical handler 'property' must be registered with the reader (filter), in order to enable this handling. The same is true for the DeclHandler. I didn't download the source from O'Reilly, but rather built the source by hand to get more intimate with the individual steps outlined in the examples. But it required me to download the source eventually in order to find this omission. (106) Figure 5-2; DOMI implementation.. ==> DOM implementation {112} case Node.COMMENT_NODE: writer.write(indentLevel + "< !--" + node.getNodeValue() + "--> "); writer.write(lineSeparator); break; should be: case Node.COMMENT_NODE: writer.write(indentLevel + ""); writer.write(lineSeparator); break; The difference is there is an unwanted space around and . (shoud be "" not "--> ") {113} bottom example; You should close the writer after use, eg. writer.close();. {118} Bottom of the page; At the end: writer.write(""); to: writer.write(""); {119} Middle of the page; The lines: System.out.println(" PUBLIC \"" + docType.getPublicId() + "\" "); should be: writer.write(" PUBLIC \"" + docType.getPublicId() + "\" "); (Safari in 5.2.3.3) down near the bottom: case Node.DOCUMENT_TYPE_NODE: DocumentType docType = (DocumentType)node; writer.write(""; writer.write(lineSeparator); break; It's missing a parenthesis - Original: writer.write("\"" + docType.getSystemId( ) + "\">"; Corrected: writer.write("\"" + docType.getSystemId( ) + "\">"); {120} Code in Results section; A File object called outputFile is declared at the beginning of the code block. A functionally equivalent File object is declared in the added code at serializer.serialize(doc, new File(outputFilename)); instead it should be serializer.serialize(doc,outputFile); (121) In the "Warning" box at the bottom; on the forth line from the bottom it reads "are in the org.apache.xml.serialize". I think, the work "package" is missing here, either before or after the package name. {123-124} bottom code example; The code example at the bottom of page 123 incorporates a try/catch block so that 'doc' is only defined within the block. Consequently the reference to 'doc' outside the block on the top of page 124 will fail to compile [131] 3rd paragraph; can't find the createDocType() method referred to as being in appendix A. a simple example would have been nice even though the author does not use it in the example. {134} last block, under // Description of item; The line which reads: Text descriptionText = doc.createText(description); Should read: Text descriptionText = doc.createTextNode(description); {135} just after the //Remove and recreate description; In the book You wrote: root.removeChild(descriptionElement); while in the code I downloaded from this site, at the following path: 9780596001971/ch06/src/javaxml2/UpdateItemServlet.java the following code is shown: // Remove and recreate description Range range = ((DocumentRange)doc).createRange(); range.setStartBefore(descriptionElement.getFirstChild()); range.setEndAfter(descriptionElement.getLastChild()); range.deleteContents(); Which is the better solution? (136) 2nd paragraph; You wrote: 'The code grabs the root element, and then uses the getElementsByTagName() method....' The used method is getElementsByTagNameNS(docNS, "..."); [154] code example at top of page; Code example will not compile. In Java nn interface cannot implement and interface. The correct syntax is extends. In a book about Java and XML we should expect correct basic Java syntax. The code: public interface StyledView implements AbstractView Must be changed to: public interface StyledView extends AbstractView The same mistake is on page 152 fifth paragraph. The rather misleading statement is made that "... org.w3c.dom.Node interface implementing the org.w3c.dom.events.EventTarget interface..." should be changed to ...class (e.g. org.apache.xerces.dom.NodeImpl) implementing the org.w3c.dom.Node interface also implements the org.w3c.dom.events.EventTarget interface ... (159) 2nd paragraph under "The Dreaded WRONG DOCUMENT Exception" header; "to use a node from a different document requires passing that node into the target document's insertNode() method."

Should read...

"to use a node from a different document requires passing that node into the target document's importNode() method."

Change is from insertNode() to importNode(). This is clarified and correct in the remainder of the section. (172) 3rd paragraph, line 4; "use it is a pointer" should probably be "use it as a pointer". [174] Example 7-4 Updated Output from PropsToXML; This example shows two classpath elements under the enhydra element. The code should prevent this from happening since it checks for an existing element. In fact when I run the code I (correctly?) only get one classpath element created as shown below. How does one explain this discrepancy? "." ":" org.enhydra.multiServer.bootstrap.Bootstrap "./bootstrap.conf" "org.apache.xerces.parsers.SAXParser" I obtain a similar discrepancy with regard to the Ouput using attributes example on page 175 - again only one classpath element, while the book shows two [174] last (unlabelled) code sample on page; The wrong Element is being used with setAttribute(). Instead of Attribute attribute = new Attribute("value", propertyValue); current.setAttribute(attribute); current.addContent(last); it should be Attribute attribute = new Attribute("value", propertyValue); last.setAttribute(attribute); current.setAttribute(last); [182] code example; The method loadFromElements() does not work correctly for mixed content. It assumes incorrectly that if we have an element value, then we have no children. Consider the following XML showing the element as having mixed content (which it should). "." ":" org.enhydra.multiServer.bootstrap.Bootstrap "./bootstrap.conf" "org.apache.xerces.parsers.SAXParser" The code in the bokk will result in the following output XML (we have lost the classpath separator, because of the mixed content): "." org.enhydra.multiServer.bootstrap.Bootstrap "./bootstrap.conf" "org.apache.xerces.parsers.SAXParser" My changes below seem to correct this problem: // OLD CODE COMMENTED OUT // See if we have an element value // if ((text == null) || (text.equals(""))) { // If no text, recurse on children // loadFromElements(current.getChildren(), baseName); // } else { // If text, this is a property // setProperty(baseName.toString(), text); // } // NEW CODE TO REPLACE FLAWED LOGIC ABOVE if ((text != null) && (!(text.equals("")))) { // if we have text, create a property setProperty(baseName.toString(), text); } if (current.hasChildren()) { // if we have children, recurse loadFromElements(current.getChildren(), baseName); } The code above will result in the following (more correct) output (the element retains its mixed content): "." ":" org.enhydra.multiServer.bootstrap.Bootstrap "./bootstrap.conf" "org.apache.xerces.parsers.SAXParser" (196) The code shown about the setExpandEntities() method; You wrote the following code: builder.setExpandEnitites(false); while it should be: builder.setExpandEntities(false); (197) 2nd paragraph, last sentence; "With this value set to FALSE (the default), you'd get the resolved content". It appears that FALSE should read TRUE. Previous paragraphs indicate that ExpandEntities defaults to TRUE and the behavior described in the sentence in question appears to be the TRUE case. (207) Source code for Chapt 7: XMLProperties.java and Chapt 8: ElementNode.java; There appear to be typo errors in the source codes: Chapter 7, XMLProperties.java, line 200: doc.getMixedContent().add(0, comment); should read as doc.getContent().add(0, comment);. Chapter 8, ElementNode.java, line 134: Iterator i = decorated.getMixedContent().iterator(); should read as Iterator i = decorated.getContent().iterator();. There is a similar in the Example 8-6, p 207 in the book. {213} public void valueChanged( ... ); The valueChanged function does not handle the special case when clicking on the top node in the tree (containing the filename). Therefore a ClassCastException occurs when trying to convert the String to a JDOMNode. I used the following code instead, and this seemed to remove the problem: public void valueChanged( TreeSelectionEvent e ) { TreePath path = selectionModel.getLeadSelectionPath(); if( path != null ) { Object selection = ((DefaultMutableTreeNode)path.getLastPathComponent() ).getUserObject(); if( selection instanceof JDOMNode ) { buildXPath( (JDOMNode)selection ); } } } [Note: I used the Text class instead of String in the TextNode class. But I don 't think this caused any side effects. ] {230} Example 9-4 (continued); Checking the JavaDoc and class files, I can find no parse() method for javax.xml.parsers.DocumentBuilder taking an InputStream and HandlerBase as parameters. In fact, I can find no parse() method which takes a HandlerBase parameter at all. I question the code below which looks like a SAXParser.parse() invocation (see pp. 226-227): // Use an InputStream Document doc = builder.parse(myInputStream, myHandlerBaseInstance); I did find two overloaded DocumentBuilder.parse() methods taking an InputStream as a parameter and returning an org.w3c.dom.Document: Document parse(InputStream is) and Document parse(InputStream is, String systemID) {236} first paragraph; Using setErrorListener() on the TransformerFactory DOES NOT set you up for dealing with errors that occur during transformation. The error event listener for the TransformerFactory is used for the processing of transformation instructions, and not for the transformation itself. Using setErrorListener() on the Transformer DOES set you up for dealing with errors that occur during transformation. You must first obtain the Transformer from the TransformerFactory. It is interesting to note that the ErrorListener interface parameter is the same for both. {237} code example at top of page; There is no setErrorResolver() method for the TransformerFactory. We might however, code as follows: // Configure the factory factory.setErrorListener(myFactoryErrorListener); factory.setURIResolver(myURIResolver); // Get a transformer to work with Transformer transformer = factory.newTransformer(new StreamSource("foundation.xsl")); transformer.setErrorListener(myTransformerErrorLstener); (241) first line of code, between 2nd and 3rd paragraphs of DEFAULT PARSERS pa rt; It might not be such a major mistake, as it is easy to identify whats missing: It can be read on the book: "javax.xml.parsers.SAXParserFactoryorg.apache.xerces.XercesFactory" and I believe it should be read as "javax.xml.parsers.SAXParserFactory = org.apache.xerces.XercesFactory" {260} 3rd line of code; missing a '>' at the tag. Simple minor trouble. {301} code at bottom of page; I have the June 2000 printing of the book. As the text on the page says this book is not about threading, but it does appear that the code has a thread error. The code reads: public boolean addEvent (String eventName, Date evenTime) { // Add this event to the list of events if (!events.contains(eventName)) { events.addElement(eventName); eventDetails.put (eventName, eventTime); eventsSorted = false; // Start thread on server sorting SortedEventsThread sorter = new SortEventsThread(); sorter.start(); } } The code for sorting is on pages 299-300. I don't reproduce it all here, but the pseudo-code is as follows: private synchronized sortEvents() { if (eventsSorted) { return; } String eventNames[] = new String [events.size()]; events.copyInto(eventNames); // sort eventNames Vector sortedEvents = new Vector(); // copy eventNames into sortedEvents events = sortedEvents; eventsSorted = true; } The trouble seems to me that addEvents() is not synchronized. This could lead to the following scenario: (1) Invocation 1 calls addEvent, kicks off Thread 1 to start sorting. It gets suspended somewhere in the middle of the sort routine (after filling in eventNames). (2) Invocation 2 calls addEvent and completes all the way up to the part before it instantiates the "sorter" variable and then gets suspended. It can do this because addEvent is not synchronized. (3) Thread 1 completes it sort routine. "events" is set to "sortedEvents" (note that this does not contain Invocation 2's new element) and eventsSorted is set to true. (4) Invocation 2 kicks off a new thread to do the sorting, but since eventsSorted is true it simply returns. In this scenario we lose Invocation 2's addElement. I think you need to synchronize around the events Vector in this case. (310) 3rd line from bottom; There its "LightweightXmlRPcServer", whereas in the listing on the following page its "LightweightXmlRpcServer" (wrong capitalization for "p") [330] Bottom NOTE section - renaming jaxp.jar and parser.jar; Even after renaming, Tomcat loads the new z_*.jar files before the added xerces.jar file (which today is actually xercesImpl.jar and xmlParserAPIs.jar) and then when testing the 'list' method you get a: D:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list Ouch, the call failed: Fault Code = SOAP-ENV:Server.Exception: Fault String = java.lang.NoSuchMethodError This error does not appear on the troubleshooting section of Apache SOAP documentation. To get the service running, simply remove jaxp.jar and parser.jar from your Tomcat/lib directory. {345} section starting 'Now recreate your service jar file...'; reployment command line reads (gandalf)/9780596001971/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml but it should contain the delopyment parameter, so should read (gandalf)/9780596001971/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter deploy xml/CDCatalogDD.xml (347) I/O example near bottom of page.; Actually, this very minor error is in the on-line sample for chapter 12, and I can only presume that it is in the print version as well. I have the book on order, but started with this chapter since it was available. This is following example 12-10 in the on-line version. Tony Rice is the artist, Manzanita is the title. Nice album, by the way. INCORRECT: C:\9780596001971\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill" Adding CD titled 'Tony Rice' by 'Manzanita', on the label Sugar Hill Successful CD Addition. CORRECT: C:\9780596001971\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Manzanita" "Tony Rice" "Sugar Hill" Adding CD titled 'Manzanita' by 'Tony Rice', on the label Sugar Hill Successful CD Addition. (371) last line; its "arragements" where is should be "arrangements" (373) first paragraph; it should be "returning a hashtable" instead of "retuning a hashtable" (387) 4th paragraph, sect 16.2.5.4; Now gthat we have a prepared statement, we can set the VALUES "Now that" (511) 4th paragraph; The 4th paragraph contains the following sentence- 'The lifespan of a lion is approx. 3-4 years.' This is not accurate, 15-18 in the wild is most likely.