1 52 53 package freemarker.ext.xml; 54 55 import java.io.StringWriter ; 56 import java.util.List ; 57 58 import org.jaxen.Context; 59 import org.jaxen.NamespaceContext; 60 import org.jaxen.dom.DOMXPath; 61 import org.w3c.dom.Attr ; 62 import org.w3c.dom.Document ; 63 import org.w3c.dom.DocumentType ; 64 import org.w3c.dom.Element ; 65 import org.w3c.dom.NamedNodeMap ; 66 import org.w3c.dom.Node ; 67 import org.w3c.dom.NodeList ; 68 import org.w3c.dom.ProcessingInstruction ; 69 import org.w3c.dom.Text ; 70 import freemarker.template.TemplateModelException; 71 import freemarker.template.utility.StringUtil; 72 73 77 class DomNavigator extends Navigator { 78 DomNavigator() { 79 } 80 81 void getAsString(Object node, StringWriter sw) { 82 outputContent((Node )node, sw.getBuffer()); 83 } 84 85 private void outputContent(Node n, StringBuffer buf) { 86 switch(n.getNodeType()) { 87 case Node.ATTRIBUTE_NODE: { 88 buf.append(' ') 89 .append(getQualifiedName(n)) 90 .append("=\"") 91 .append(StringUtil.XMLEncNA(n.getNodeValue())) .append('"'); 93 break; 94 } 95 case Node.CDATA_SECTION_NODE: { 96 buf.append("<![CDATA[").append(n.getNodeValue()).append("]]>"); 97 break; 98 } 99 case Node.COMMENT_NODE: { 100 buf.append("<!--").append(n.getNodeValue()).append("-->"); 101 break; 102 } 103 case Node.DOCUMENT_NODE: { 104 outputContent(n.getChildNodes(), buf); 105 break; 106 } 107 case Node.DOCUMENT_TYPE_NODE: { 108 buf.append("<!DOCTYPE ").append(n.getNodeName()); 109 DocumentType dt = (DocumentType )n; 110 if(dt.getPublicId() != null) { 111 buf.append(" PUBLIC \"").append(dt.getPublicId()).append('"'); 112 } 113 if(dt.getSystemId() != null) { 114 buf.append('"').append(dt.getSystemId()).append('"'); 115 } 116 if(dt.getInternalSubset() != null) { 117 buf.append(" [").append(dt.getInternalSubset()).append(']'); 118 } 119 buf.append('>'); 120 break; 121 } 122 case Node.ELEMENT_NODE: { 123 buf.append('<').append(getQualifiedName(n)); 124 outputContent(n.getAttributes(), buf); 125 buf.append('>'); 126 outputContent(n.getChildNodes(), buf); 127 buf.append("</").append(getQualifiedName(n)).append('>'); 128 break; 129 } 130 case Node.ENTITY_NODE: { 131 outputContent(n.getChildNodes(), buf); 132 break; 133 } 134 case Node.ENTITY_REFERENCE_NODE: { 135 buf.append('&').append(n.getNodeName()).append(';'); 136 break; 137 } 138 case Node.PROCESSING_INSTRUCTION_NODE: { 139 buf.append("<?").append(n.getNodeName()).append(' ').append(n.getNodeValue()).append("?>"); 140 break; 141 } 142 case Node.TEXT_NODE: { 143 buf.append(StringUtil.XMLEncNQG(n.getNodeValue())); 144 break; 145 } 146 } 147 } 148 149 private void outputContent(NodeList nodes, StringBuffer buf) { 150 for(int i = 0; i < nodes.getLength(); ++i) { 151 outputContent(nodes.item(i), buf); 152 } 153 } 154 155 private void outputContent(NamedNodeMap nodes, StringBuffer buf) { 156 for(int i = 0; i < nodes.getLength(); ++i) { 157 outputContent(nodes.item(i), buf); 158 } 159 } 160 161 void getChildren(Object node, String localName, String namespaceUri, List result) { 162 if("".equals(namespaceUri)) { 163 namespaceUri = null; 164 } 165 NodeList children = ((Node )node).getChildNodes(); 166 for(int i = 0; i < children.getLength(); ++i) { 167 Node subnode = children.item(i); 168 if(subnode.getNodeType() == Node.ELEMENT_NODE || subnode.getNodeType() == Node.TEXT_NODE) { 170 if(localName == null || (equal(subnode.getNodeName(), localName) && equal(subnode.getNamespaceURI(), namespaceUri))) { 171 result.add(subnode); 172 } 173 } 174 } 175 } 176 177 void getAttributes(Object node, String localName, String namespaceUri, List result) { 178 if(node instanceof Element ) { 179 Element e = (Element )node; 180 if(localName == null) { 181 NamedNodeMap atts = e.getAttributes(); 182 for(int i = 0; i < atts.getLength(); ++i) { 183 result.add(atts.item(i)); 184 } 185 } 186 else { 187 if("".equals(namespaceUri)) { 188 namespaceUri = null; 189 } 190 Attr attr = e.getAttributeNodeNS(namespaceUri, localName); 191 if(attr != null) { 192 result.add(attr); 193 } 194 } 195 } 196 else if (node instanceof ProcessingInstruction ) { 197 ProcessingInstruction pi = (ProcessingInstruction )node; 198 if ("target".equals(localName)) { 199 result.add(createAttribute(pi, "target", pi.getTarget())); 200 } 201 else if ("data".equals(localName)) { 202 result.add(createAttribute(pi, "data", pi.getData())); 203 } 204 else { 205 ; 208 } 209 } else if (node instanceof DocumentType ) { 210 DocumentType doctype = (DocumentType )node; 211 if ("publicId".equals(localName)) { 212 result.add(createAttribute(doctype, "publicId", doctype.getPublicId())); 213 } 214 else if ("systemId".equals(localName)) { 215 result.add(createAttribute(doctype, "systemId", doctype.getSystemId())); 216 } 217 else if ("elementName".equals(localName)) { 218 result.add(createAttribute(doctype, "elementName", doctype.getNodeName())); 219 } 220 } 221 } 222 223 private Attr createAttribute(Node node, String name, String value) { 224 Attr attr = node.getOwnerDocument().createAttribute(name); 225 attr.setNodeValue(value); 226 return attr; 227 } 228 229 void getDescendants(Object node, List result) { 230 NodeList children = ((Node )node).getChildNodes(); 231 for(int i = 0; i < children.getLength(); ++i) { 232 Node subnode = children.item(i); 233 if(subnode.getNodeType() == Node.ELEMENT_NODE) { 234 result.add(subnode); 235 getDescendants(subnode, result); 236 } 237 } 238 } 239 240 Object getParent(Object node) { 241 return ((Node )node).getParentNode(); 242 } 243 244 Object getDocument(Object node) { 245 return ((Node )node).getOwnerDocument(); 246 } 247 248 Object getDocumentType(Object node) { 249 return 250 node instanceof Document 251 ? ((Document )node).getDoctype() 252 : null; 253 } 254 255 void getContent(Object node, List result) { 256 NodeList children = ((Node )node).getChildNodes(); 257 for(int i = 0; i < children.getLength(); ++i) { 258 result.add(children.item(i)); 259 } 260 } 261 262 String getText(Object node) { 263 StringBuffer buf = new StringBuffer (); 264 if(node instanceof Element ) { 265 NodeList children = ((Node )node).getChildNodes(); 266 for(int i = 0; i < children.getLength(); ++i) { 267 Node child = children.item(i); 268 if(child instanceof Text ) { 269 buf.append(child.getNodeValue()); 270 } 271 } 272 return buf.toString(); 273 } 274 else { 275 return ((Node )node).getNodeValue(); 276 } 277 } 278 279 String getLocalName(Object node) { 280 return ((Node )node).getNodeName(); 281 } 282 283 String getNamespacePrefix(Object node) { 284 return ((Node )node).getPrefix(); 285 } 286 287 String getNamespaceUri(Object node) { 288 return ((Node )node).getNamespaceURI(); 289 } 290 291 String getType(Object node) { 292 switch(((Node )node).getNodeType()) { 293 case Node.ATTRIBUTE_NODE: { 294 return "attribute"; 295 } 296 case Node.CDATA_SECTION_NODE: { 297 return "cdata"; 298 } 299 case Node.COMMENT_NODE: { 300 return "comment"; 301 } 302 case Node.DOCUMENT_NODE: { 303 return "document"; 304 } 305 case Node.DOCUMENT_TYPE_NODE: { 306 return "documentType"; 307 } 308 case Node.ELEMENT_NODE: { 309 return "element"; 310 } 311 case Node.ENTITY_NODE: { 312 return "entity"; 313 } 314 case Node.ENTITY_REFERENCE_NODE: { 315 return "entityReference"; 316 } 317 case Node.PROCESSING_INSTRUCTION_NODE: { 318 return "processingInstruction"; 319 } 320 case Node.TEXT_NODE: { 321 return "text"; 322 } 323 } 324 return "unknown"; 325 } 326 327 XPathEx createXPathEx(String xpathString) throws TemplateModelException 328 { 329 try { 330 return new DomXPathEx(xpathString); 331 } 332 catch(Exception e) { 333 throw new TemplateModelException(e); 334 } 335 } 336 337 private static final class DomXPathEx 338 extends 339 DOMXPath 340 implements 341 XPathEx 342 { 343 DomXPathEx(String path) 344 throws 345 Exception 346 { 347 super(path); 348 } 349 350 public List selectNodes(Object object, NamespaceContext namespaces) 351 throws 352 TemplateModelException 353 { 354 Context context = getContext(object); 355 context.getContextSupport().setNamespaceContext(namespaces); 356 try { 357 return selectNodesForContext(context); 358 } 359 catch(Exception e) { 360 throw new TemplateModelException(e); 361 } 362 } 363 } 364 } 365 | Popular Tags |