1 52 53 package freemarker.ext.dom; 54 55 import freemarker.template.*; 56 import freemarker.template.utility.StringUtil; 57 import freemarker.core.Environment; 58 import org.w3c.dom.*; 59 import java.util.List ; 60 import java.util.ArrayList ; 61 62 class NodeListModel extends SimpleSequence implements TemplateHashModel { 63 64 NodeModel contextNode; 65 XPathSupport xpathSupport; 66 67 private static ObjectWrapper nodeWrapper = new ObjectWrapper() { 68 public TemplateModel wrap(Object obj) { 69 if (obj instanceof NodeModel) { 70 return (NodeModel) obj; 71 } 72 return NodeModel.wrap((Node) obj); 73 } 74 }; 75 76 77 NodeListModel(Node node) { 78 this(NodeModel.wrap(node)); 79 } 80 81 NodeListModel(NodeModel contextNode) { 82 super(nodeWrapper); 83 this.contextNode = contextNode; 84 } 85 86 NodeListModel(NodeList nodeList, NodeModel contextNode) { 87 super(nodeWrapper); 88 for (int i=0; i<nodeList.getLength();i++) { 89 list.add(nodeList.item(i)); 90 } 91 this.contextNode = contextNode; 92 } 93 94 NodeListModel(NamedNodeMap nodeList, NodeModel contextNode) { 95 super(nodeWrapper); 96 for (int i=0; i<nodeList.getLength();i++) { 97 list.add(nodeList.item(i)); 98 } 99 this.contextNode = contextNode; 100 } 101 102 NodeListModel(List list, NodeModel contextNode) { 103 super(list, nodeWrapper); 104 this.contextNode = contextNode; 105 } 106 107 NodeListModel filterByName(String name) throws TemplateModelException { 108 NodeListModel result = new NodeListModel(contextNode); 109 int size = size(); 110 if (size == 0) { 111 return result; 112 } 113 Environment env = Environment.getCurrentEnvironment(); 114 for (int i = 0; i<size; i++) { 115 NodeModel nm = (NodeModel) get(i); 116 if (nm instanceof ElementModel) { 117 if (((ElementModel) nm).matchesName(name, env)) { 118 result.add(nm); 119 } 120 } 121 } 122 return result; 123 } 124 125 public boolean isEmpty() { 126 return size() == 0; 127 } 128 129 public TemplateModel get(String key) throws TemplateModelException { 130 if (size() ==1) { 131 NodeModel nm = (NodeModel) get(0); 132 return nm.get(key); 133 } 134 if (key.equals("@@markup") 135 || key.equals("@@nested_markup") 136 || key.equals("@@text")) 137 { 138 StringBuffer result = new StringBuffer (); 139 for (int i=0; i<size(); i++) { 140 NodeModel nm = (NodeModel) get(i); 141 TemplateScalarModel textModel = (TemplateScalarModel) nm.get(key); 142 result.append(textModel.getAsString()); 143 } 144 return new SimpleScalar(result.toString()); 145 } 146 if (StringUtil.isXMLID(key) 147 || ((key.startsWith("@") && StringUtil.isXMLID(key.substring(1)))) 148 || key.equals("*") || key.equals("**") || key.equals("@@") || key.equals("@*")) 149 { 150 NodeListModel result = new NodeListModel(contextNode); 151 for (int i=0; i<size(); i++) { 152 NodeModel nm = (NodeModel) get(i); 153 if (nm instanceof ElementModel) { 154 TemplateSequenceModel tsm = (TemplateSequenceModel) ((ElementModel) nm).get(key); 155 int size = tsm == null ? 0 : tsm.size(); 156 for (int j=0; j < size; j++) { 157 result.add(tsm.get(j)); 158 } 159 } 160 } 161 if (result.size() == 1) { 162 return result.get(0); 163 } 164 return result; 165 } 166 XPathSupport xps = getXPathSupport(); 167 if (xps != null) { 168 Object context = (size() == 0) ? null : rawNodeList(); 169 return xps.executeQuery(context, key); 170 } 171 throw new TemplateModelException("Key: '" + key + "' is not legal for a node sequence (" 172 + this.getClass().getName() + "). This node sequence contains " + size() + " node(s). " 173 + "Some keys are valid only for node sequences of size 1. " 174 + "If you use Xalan (instead of Jaxen), XPath expression keys work only with " 175 + "node lists of size 1."); 176 } 177 178 private List rawNodeList() throws TemplateModelException { 179 int size = size(); 180 ArrayList al = new ArrayList (size); 181 for (int i=0; i<size; i++) { 182 al.add(((NodeModel) get(i)).node); 183 } 184 return al; 185 } 186 187 XPathSupport getXPathSupport() throws TemplateModelException { 188 if (xpathSupport == null) { 189 if (contextNode != null) { 190 xpathSupport = contextNode.getXPathSupport(); 191 } 192 else if (size() >0) { 193 xpathSupport = ((NodeModel) get(0)).getXPathSupport(); 194 } 195 } 196 return xpathSupport; 197 } 198 } | Popular Tags |