/** * PartsCheck.java * * DOM Usage example from the O'Reilly _XML in a Nutshell_ book. * */ // we'll use the Apache Software Foundation's Xerces parser. import org.apache.xerces.parsers.*; import org.apache.xerces.framework.*; // import the DOM interfaces import org.w3c.dom.*; import org.xml.sax.*; // get the necessary java support classes import java.io.*; import java.util.*; /** * This class is designed to check the parts list of an XML document that * represents a piece of furniture for validity. It uses the DOM to * analyze the actual furniture description and then check it against the * parts list that is embedded in the document. */ public class PartsCheck { // contains the true part count, keyed by part number HashMap m_hmTruePartsList = new HashMap(); /** * The main function that allows this class to be invoked from the command * line. Check each document provided on the command line for validity. */ public static void main(String[] args) { PartsCheck pc = new PartsCheck(); try { for (int i = 0; i < args.length; i++) { pc.validatePartsList(args[i]); } } catch (Exception e) { System.err.println(e); } } /** * Empty constructor that allows this object to be instantiated. */ public PartsCheck() { } /** * Given a system identifier for an XML document, this function compares * the actual parts used to the declared parts list within the document. It * prints warnings to standard error if the lists don't agree. */ public void validatePartsList(String strXMLSysID) throws IOException, SAXException { // create a new parser DOMParser dp = new DOMParser(); // parse the document and get the DOM Document interface dp.parse(strXMLSysID); Document doc = dp.getDocument(); // get an accurate parts list count countParts(doc.getDocumentElement(), 1); // compare it to the parts list in the document reconcilePartsList(doc); } /** * Updates the true parts list by adding the count to the current count * for the part number given. */ private void recordPart(String strPartNum, int cCount) { if (!m_hmTruePartsList.containsKey(strPartNum)) { // this part isn't listed yet m_hmTruePartsList.put(strPartNum, new Integer(cCount)); } else { // update the count Integer cUpdate = (Integer)m_hmTruePartsList.get(strPartNum); m_hmTruePartsList.put(strPartNum, new Integer(cUpdate.intValue() + cCount)); } } /** * Counts the parts referenced by and below the given node. */ private void countParts(Node nd, int cRepeat) { // start the local repeat count at 1 int cLocalRepeat = 1; Node ndTemp; if ((ndTemp = nd.getAttributes().getNamedItem("repeat")) != null) { // this node specifies a repeat count for its children cLocalRepeat = Integer.parseInt(ndTemp.getNodeValue()); } if ((ndTemp = nd.getAttributes().getNamedItem("part_num")) != null) { // start the count at 1 int cCount = 1; String strPartNum = ndTemp.getNodeValue(); if ((ndTemp = nd.getAttributes().getNamedItem("count")) != null) { // more than one part needed by this node cCount = Integer.parseInt(ndTemp.getNodeValue()); } // multiply the local count by the repeat passed in from the parent cCount *= cRepeat; // add the new parts count to the total recordPart(strPartNum, cCount); } // now process the children NodeList nl = nd.getChildNodes(); Node ndCur; for (int i = 0; i < nl.getLength(); i++) { ndCur = nl.item(i); if (ndCur.getNodeType() == Node.ELEMENT_NODE) { // recursively count the parts for the child, using the local repeat countParts(ndCur, cLocalRepeat); } } } /** * This method reconciles the true parts list against the list in the document. */ private void reconcilePartsList(Document doc) { Iterator iReal = m_hmTruePartsList.keySet().iterator(); String strPartNum; int cReal; Node ndCheck; // loop through all of the parts in the true parts list while (iReal.hasNext()) { strPartNum = (String)iReal.next(); cReal = ((Integer)m_hmTruePartsList.get(strPartNum)).intValue(); // find the part list element in the document ndCheck = doc.getElementById(strPartNum); if (ndCheck == null) { // this part isn't even listed! System.err.println("missing element for part #" + strPartNum + " (count " + cReal + ")"); } else { Node ndTemp; if ((ndTemp = ndCheck.getAttributes().getNamedItem("count")) != null) { int cCheck = Integer.parseInt(ndTemp.getNodeValue()); if (cCheck != cReal) { // counts don't agree System.err.println(" element for part #" + strPartNum + " is incorrect: true part count = " + cReal + " (count in document is " + cCheck + ")"); } } else { // they didn't provide a count for this part! System.err.println("missing count attribute for part #" + strPartNum + " (count " + cReal + ")"); } } } } }