1 52 53 package freemarker.ext.dom; 54 55 import freemarker.template.*; 56 import freemarker.core.Environment; 57 import org.w3c.dom.*; 58 import org.w3c.dom.traversal.NodeIterator; 59 import org.apache.xpath.*; 60 import org.apache.xpath.objects.*; 61 import org.apache.xml.utils.PrefixResolver; 62 import java.util.List ; 63 import javax.xml.transform.TransformerException ; 64 65 71 72 class XalanXPathSupport implements XPathSupport { 73 74 private XPathContext xpathContext = new XPathContext(); 75 76 81 private static final String ERRMSG_EMPTY_NODE_SET 82 = "Cannot perform an XPath query against an empty node set."; 83 84 synchronized public TemplateModel executeQuery(Object context, String xpathQuery) throws TemplateModelException { 85 if (!(context instanceof Node)) { 86 if (context != null) { 87 if (isNodeList(context)) { 88 int cnt = ((List ) context).size(); 89 if (cnt != 0) { 90 throw new TemplateModelException( 91 "Cannot perform an XPath query against a node set of " + cnt 92 + " nodes. Expecting a single node."); 93 } else { 94 throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET); 95 } 96 } else { 97 throw new TemplateModelException( 98 "Cannot perform an XPath query against a " + context.getClass().getName() 99 + ". Expecting a single org.w3c.dom.Node."); 100 } 101 } else { 102 throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET); 103 } 104 } 105 Node node = (Node) context; 106 try { 107 XPath xpath = new XPath(xpathQuery, null, customPrefixResolver, XPath.SELECT, null); 108 int ctxtNode = xpathContext.getDTMHandleFromNode(node); 109 XObject xresult = xpath.execute(xpathContext, ctxtNode, customPrefixResolver); 110 if (xresult instanceof XNodeSet) { 111 NodeListModel result = new NodeListModel(node); 112 result.xpathSupport = this; 113 NodeIterator nodeIterator = xresult.nodeset(); 114 Node n; 115 do { 116 n = nodeIterator.nextNode(); 117 if (n != null) { 118 result.add(n); 119 } 120 } while (n != null); 121 return result.size() == 1 ? result.get(0) : result; 122 } 123 if (xresult instanceof XBoolean) { 124 return ((XBoolean) xresult).bool() ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; 125 } 126 if (xresult instanceof XNull) { 127 return null; 128 } 129 if (xresult instanceof XString) { 130 return new SimpleScalar(xresult.toString()); 131 } 132 if (xresult instanceof XNumber) { 133 return new SimpleNumber(new Double (((XNumber) xresult).num())); 134 } 135 throw new TemplateModelException("Cannot deal with type: " + xresult.getClass().getName()); 136 } catch (TransformerException te) { 137 throw new TemplateModelException(te); 138 } 139 } 140 141 private static PrefixResolver customPrefixResolver = new PrefixResolver() { 142 143 public String getNamespaceForPrefix(String prefix, Node node) { 144 return getNamespaceForPrefix(prefix); 145 } 146 147 public String getNamespaceForPrefix(String prefix) { 148 if (prefix.equals(Template.DEFAULT_NAMESPACE_PREFIX)) { 149 return Environment.getCurrentEnvironment().getDefaultNS(); 150 } 151 return Environment.getCurrentEnvironment().getNamespaceForPrefix(prefix); 152 } 153 154 public String getBaseIdentifier() { 155 return null; 156 } 157 158 public boolean handlesNullPrefixes() { 159 return false; 160 } 161 }; 162 163 166 private static boolean isNodeList(Object context) { 167 if (context instanceof List ) { 168 List ls = (List ) context; 169 int ln = ls.size(); 170 for (int i = 0; i < ln; i++) { 171 if (!(ls.get(i) instanceof Node)) { 172 return false; 173 } 174 } 175 return true; 176 } else { 177 return false; 178 } 179 } 180 } | Popular Tags |