1 package com.ibatis.common.xml; 2 3 import org.w3c.dom.*; 4 import org.xml.sax.*; 5 6 import javax.xml.parsers.DocumentBuilder ; 7 import javax.xml.parsers.DocumentBuilderFactory ; 8 import javax.xml.parsers.FactoryConfigurationError ; 9 import javax.xml.parsers.ParserConfigurationException ; 10 import java.io.IOException ; 11 import java.io.OutputStreamWriter ; 12 import java.io.Reader ; 13 import java.util.*; 14 15 import com.ibatis.common.exception.NestedRuntimeException; 16 17 24 public class NodeletParser { 25 26 private Map letMap = new HashMap(); 27 28 private boolean validation; 29 private EntityResolver entityResolver; 30 31 41 public void addNodelet(String xpath, Nodelet nodelet) { 42 letMap.put(xpath, nodelet); 43 } 44 45 48 public void parse(Reader reader) throws NodeletException { 49 try { 50 Document doc = createDocument(reader); 51 parse(doc.getLastChild()); 52 } catch (Exception e) { 53 throw new NodeletException("Error parsing XML. Cause: " + e, e); 54 } 55 } 56 57 60 public void parse(Node node) { 61 Path path = new Path(); 62 processNodelet(node, "/"); 63 process(node, path); 64 } 65 66 70 private void process(Node node, Path path) { 71 if (node instanceof Element) { 72 String elementName = node.getNodeName(); 74 path.add(elementName); 75 processNodelet(node, path.toString()); 76 processNodelet(node, new StringBuffer ("//").append(elementName).toString()); 77 78 NamedNodeMap attributes = node.getAttributes(); 80 int n = attributes.getLength(); 81 for (int i = 0; i < n; i++) { 82 Node att = attributes.item(i); 83 String attrName = att.getNodeName(); 84 path.add("@" + attrName); 85 processNodelet(att, path.toString()); 86 processNodelet(node, new StringBuffer ("//@").append(attrName).toString()); 87 path.remove(); 88 } 89 90 NodeList children = node.getChildNodes(); 92 for (int i = 0; i < children.getLength(); i++) { 93 process(children.item(i), path); 94 } 95 path.add("end()"); 96 processNodelet(node, path.toString()); 97 path.remove(); 98 path.remove(); 99 } else if (node instanceof Text) { 100 path.add("text()"); 102 processNodelet(node, path.toString()); 103 processNodelet(node, "//text()"); 104 path.remove(); 105 } 106 } 107 108 private void processNodelet(Node node, String pathString) { 109 Nodelet nodelet = (Nodelet) letMap.get(pathString); 110 if (nodelet != null) { 111 try { 112 nodelet.process(node); 113 } catch (Exception e) { 114 throw new NestedRuntimeException("Error parsing XPath '" + pathString + "'. Cause: " + e, e); 115 } 116 } 117 } 118 119 122 private Document createDocument(Reader reader) throws ParserConfigurationException , FactoryConfigurationError , 123 SAXException, IOException { 124 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 125 factory.setValidating(validation); 126 127 factory.setNamespaceAware(false); 128 factory.setIgnoringComments(true); 129 factory.setIgnoringElementContentWhitespace(false); 130 factory.setCoalescing(false); 131 factory.setExpandEntityReferences(true); 132 133 OutputStreamWriter errorWriter = new OutputStreamWriter (System.err); 134 135 DocumentBuilder builder = factory.newDocumentBuilder(); 136 builder.setEntityResolver(entityResolver); 137 builder.setErrorHandler(new ErrorHandler() { 138 public void error(SAXParseException exception) throws SAXException { 139 throw exception; 140 } 141 142 public void fatalError(SAXParseException exception) throws SAXException { 143 throw exception; 144 } 145 146 public void warning(SAXParseException exception) throws SAXException { 147 } 148 }); 149 150 return builder.parse(new InputSource(reader)); 151 } 152 153 public void setValidation(boolean validation) { 154 this.validation = validation; 155 } 156 157 public void setEntityResolver(EntityResolver resolver) { 158 this.entityResolver = resolver; 159 } 160 161 166 private static class Path { 167 168 private List nodeList = new ArrayList(); 169 170 public Path() { 171 } 172 173 public Path(String path) { 174 StringTokenizer parser = new StringTokenizer(path, "/", false); 175 while (parser.hasMoreTokens()) { 176 nodeList.add(parser.nextToken()); 177 } 178 } 179 180 public void add(String node) { 181 nodeList.add(node); 182 } 183 184 public void remove() { 185 nodeList.remove(nodeList.size() - 1); 186 } 187 188 public String toString() { 189 StringBuffer buffer = new StringBuffer ("/"); 190 for (int i = 0; i < nodeList.size(); i++) { 191 buffer.append(nodeList.get(i)); 192 if (i < nodeList.size() - 1) { 193 buffer.append("/"); 194 } 195 } 196 return buffer.toString(); 197 } 198 } 199 200 } | Popular Tags |