001: /*
002: * Copyright (c) 2003 The Visigoth Software Society. All rights
003: * reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * 2. Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowledgement:
019: * "This product includes software developed by the
020: * Visigoth Software Society (http://www.visigoths.org/)."
021: * Alternately, this acknowledgement may appear in the software itself,
022: * if and wherever such third-party acknowledgements normally appear.
023: *
024: * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025: * project contributors may be used to endorse or promote products derived
026: * from this software without prior written permission. For written
027: * permission, please contact visigoths@visigoths.org.
028: *
029: * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030: * nor may "FreeMarker" or "Visigoth" appear in their names
031: * without prior written permission of the Visigoth Software Society.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of the Visigoth Software Society. For more
049: * information on the Visigoth Software Society, please see
050: * http://www.visigoths.org/
051: */
052:
053: package freemarker.ext.xml;
054:
055: import java.io.IOException;
056: import java.io.StringWriter;
057: import java.util.Iterator;
058: import java.util.List;
059:
060: import freemarker.template.TemplateModelException;
061:
062: import org.jaxen.Context;
063: import org.jaxen.NamespaceContext;
064: import org.jaxen.jdom.JDOMXPath;
065: import org.jdom.Element;
066: import org.jdom.Attribute;
067: import org.jdom.CDATA;
068: import org.jdom.Comment;
069: import org.jdom.DocType;
070: import org.jdom.Document;
071: import org.jdom.EntityRef;
072: import org.jdom.Namespace;
073: import org.jdom.ProcessingInstruction;
074: import org.jdom.Text;
075: import org.jdom.output.XMLOutputter;
076:
077: /**
078: * @version $Id: JdomNavigator.java,v 1.3.4.2 2006/11/14 10:42:54 szegedia Exp $
079: * @author Attila Szegedi
080: */
081: class JdomNavigator extends Navigator {
082: private static final XMLOutputter OUTPUT = new XMLOutputter();
083:
084: JdomNavigator() {
085: }
086:
087: void getAsString(Object node, StringWriter sw)
088: throws TemplateModelException {
089: try {
090: if (node instanceof Element) {
091: OUTPUT.output((Element) node, sw);
092: } else if (node instanceof Attribute) {
093: Attribute attribute = (Attribute) node;
094: sw.write(" ");
095: sw.write(attribute.getQualifiedName());
096: sw.write("=\"");
097: sw.write(OUTPUT.escapeAttributeEntities(attribute
098: .getValue()));
099: sw.write("\"");
100: } else if (node instanceof Text) {
101: OUTPUT.output((Text) node, sw);
102: } else if (node instanceof Document) {
103: OUTPUT.output((Document) node, sw);
104: } else if (node instanceof ProcessingInstruction) {
105: OUTPUT.output((ProcessingInstruction) node, sw);
106: } else if (node instanceof Comment) {
107: OUTPUT.output((Comment) node, sw);
108: } else if (node instanceof CDATA) {
109: OUTPUT.output((CDATA) node, sw);
110: } else if (node instanceof DocType) {
111: OUTPUT.output((DocType) node, sw);
112: } else if (node instanceof EntityRef) {
113: OUTPUT.output((EntityRef) node, sw);
114: } else {
115: throw new TemplateModelException(node.getClass()
116: .getName()
117: + " is not a core JDOM class");
118: }
119: } catch (IOException e) {
120: throw new TemplateModelException(e);
121: }
122: }
123:
124: void getChildren(Object node, String localName,
125: String namespaceUri, List result) {
126: if (node instanceof Element) {
127: Element e = (Element) node;
128: if (localName == null) {
129: result.addAll(e.getChildren());
130: } else {
131: result.addAll(e.getChildren(localName, Namespace
132: .getNamespace("", namespaceUri)));
133: }
134: } else if (node instanceof Document) {
135: Element root = ((Document) node).getRootElement();
136: if (localName == null
137: || (equal(root.getName(), localName) && equal(root
138: .getNamespaceURI(), namespaceUri))) {
139: result.add(root);
140: }
141: }
142: }
143:
144: void getAttributes(Object node, String localName,
145: String namespaceUri, List result) {
146: if (node instanceof Element) {
147: Element e = (Element) node;
148: if (localName == null) {
149: result.addAll(e.getAttributes());
150: } else {
151: Attribute attr = e.getAttribute(localName, Namespace
152: .getNamespace("", namespaceUri));
153: if (attr != null) {
154: result.add(attr);
155: }
156: }
157: } else if (node instanceof ProcessingInstruction) {
158: ProcessingInstruction pi = (ProcessingInstruction) node;
159: if ("target".equals(localName)) {
160: result.add(new Attribute("target", pi.getTarget()));
161: } else if ("data".equals(localName)) {
162: result.add(new Attribute("data", pi.getData()));
163: } else {
164: result.add(new Attribute(localName, pi
165: .getValue(localName)));
166: }
167: } else if (node instanceof DocType) {
168: DocType doctype = (DocType) node;
169: if ("publicId".equals(localName)) {
170: result.add(new Attribute("publicId", doctype
171: .getPublicID()));
172: } else if ("systemId".equals(localName)) {
173: result.add(new Attribute("systemId", doctype
174: .getSystemID()));
175: } else if ("elementName".equals(localName)) {
176: result.add(new Attribute("elementName", doctype
177: .getElementName()));
178: }
179: }
180: }
181:
182: void getDescendants(Object node, List result) {
183: if (node instanceof Document) {
184: Element root = ((Document) node).getRootElement();
185: result.add(root);
186: getDescendants(root, result);
187: } else if (node instanceof Element) {
188: getDescendants((Element) node, result);
189: }
190: }
191:
192: private void getDescendants(Element node, List result) {
193: for (Iterator iter = node.getChildren().iterator(); iter
194: .hasNext();) {
195: Element subnode = (Element) iter.next();
196: result.add(subnode);
197: getDescendants(subnode, result);
198: }
199: }
200:
201: Object getParent(Object node) {
202: if (node instanceof Element) {
203: return ((Element) node).getParent();
204: }
205: if (node instanceof Attribute) {
206: return ((Attribute) node).getParent();
207: }
208: if (node instanceof Text) {
209: return ((Text) node).getParent();
210: }
211: if (node instanceof ProcessingInstruction) {
212: return ((ProcessingInstruction) node).getParent();
213: }
214: if (node instanceof Comment) {
215: return ((Comment) node).getParent();
216: }
217: if (node instanceof EntityRef) {
218: return ((EntityRef) node).getParent();
219: }
220: return null;
221: }
222:
223: Object getDocument(Object node) {
224: if (node instanceof Element) {
225: return ((Element) node).getDocument();
226: } else if (node instanceof Attribute) {
227: Element parent = ((Attribute) node).getParent();
228: return parent == null ? null : parent.getDocument();
229: } else if (node instanceof Text) {
230: Element parent = ((Text) node).getParent();
231: return parent == null ? null : parent.getDocument();
232: } else if (node instanceof Document)
233: return (Document) node;
234: else if (node instanceof ProcessingInstruction) {
235: return ((ProcessingInstruction) node).getDocument();
236: } else if (node instanceof EntityRef) {
237: return ((EntityRef) node).getDocument();
238: } else if (node instanceof Comment) {
239: return ((Comment) node).getDocument();
240: }
241: return null;
242: }
243:
244: Object getDocumentType(Object node) {
245: return node instanceof Document ? ((Document) node)
246: .getDocType() : null;
247: }
248:
249: void getContent(Object node, List result) {
250: if (node instanceof Element)
251: result.addAll(((Element) node).getContent());
252: else if (node instanceof Document)
253: result.addAll(((Document) node).getContent());
254: }
255:
256: String getText(Object node) {
257: if (node instanceof Element) {
258: return ((Element) node).getTextTrim();
259: }
260: if (node instanceof Attribute) {
261: return ((Attribute) node).getValue();
262: }
263: if (node instanceof CDATA) {
264: return ((CDATA) node).getText();
265: }
266: if (node instanceof Comment) {
267: return ((Comment) node).getText();
268: }
269: if (node instanceof ProcessingInstruction) {
270: return ((ProcessingInstruction) node).getData();
271: }
272: return null;
273: }
274:
275: String getLocalName(Object node) {
276: if (node instanceof Element) {
277: return ((Element) node).getName();
278: }
279: if (node instanceof Attribute) {
280: return ((Attribute) node).getName();
281: }
282: if (node instanceof EntityRef) {
283: return ((EntityRef) node).getName();
284: }
285: if (node instanceof ProcessingInstruction) {
286: return ((ProcessingInstruction) node).getTarget();
287: }
288: if (node instanceof DocType) {
289: return ((DocType) node).getElementName();
290: }
291: return null;
292: }
293:
294: String getNamespacePrefix(Object node) {
295: if (node instanceof Element) {
296: return ((Element) node).getNamespacePrefix();
297: }
298: if (node instanceof Attribute) {
299: return ((Attribute) node).getNamespacePrefix();
300: }
301: return null;
302: }
303:
304: String getNamespaceUri(Object node) {
305: if (node instanceof Element) {
306: return ((Element) node).getNamespaceURI();
307: }
308: if (node instanceof Attribute) {
309: return ((Attribute) node).getNamespaceURI();
310: }
311: return null;
312: }
313:
314: String getType(Object node) {
315: if (node instanceof Attribute) {
316: return "attribute";
317: }
318: if (node instanceof CDATA) {
319: return "cdata";
320: }
321: if (node instanceof Comment) {
322: return "comment";
323: }
324: if (node instanceof Document) {
325: return "document";
326: }
327: if (node instanceof DocType) {
328: return "documentType";
329: }
330: if (node instanceof Element) {
331: return "element";
332: }
333: if (node instanceof EntityRef) {
334: return "entityReference";
335: }
336: if (node instanceof Namespace) {
337: return "namespace";
338: }
339: if (node instanceof ProcessingInstruction) {
340: return "processingInstruction";
341: }
342: if (node instanceof Text) {
343: return "text";
344: }
345: return "unknown";
346: }
347:
348: XPathEx createXPathEx(String xpathString)
349: throws TemplateModelException {
350: try {
351: return new JDOMXPathEx(xpathString);
352: } catch (Exception e) {
353: throw new TemplateModelException(e);
354: }
355: }
356:
357: private static final class JDOMXPathEx extends JDOMXPath implements
358: XPathEx {
359: JDOMXPathEx(String path) throws Exception {
360: super (path);
361: }
362:
363: public List selectNodes(Object object,
364: NamespaceContext namespaces)
365: throws TemplateModelException {
366: Context context = getContext(object);
367: context.getContextSupport().setNamespaceContext(namespaces);
368: try {
369: return selectNodesForContext(context);
370: } catch (Exception e) {
371: throw new TemplateModelException(e);
372: }
373: }
374: }
375: }
|