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.StringWriter;
056: import java.util.Iterator;
057: import java.util.List;
058:
059: import freemarker.template.TemplateModelException;
060:
061: import org.dom4j.Attribute;
062: import org.dom4j.Branch;
063: import org.dom4j.Document;
064: import org.dom4j.DocumentType;
065: import org.dom4j.Element;
066: import org.dom4j.Node;
067: import org.dom4j.ProcessingInstruction;
068: import org.dom4j.tree.DefaultAttribute;
069: import org.jaxen.Context;
070: import org.jaxen.NamespaceContext;
071: import org.jaxen.dom4j.Dom4jXPath;
072:
073: /**
074: * @version $Id: Dom4jNavigator.java,v 1.3 2003/01/31 11:39:17 szegedia Exp $
075: * @author Attila Szegedi
076: */
077: class Dom4jNavigator extends Navigator {
078:
079: Dom4jNavigator() {
080: }
081:
082: void getAsString(Object node, StringWriter sw) {
083: sw.getBuffer().append(((Node) node).asXML());
084: }
085:
086: void getChildren(Object node, String localName,
087: String namespaceUri, List result) {
088: if (node instanceof Element) {
089: Element e = (Element) node;
090: if (localName == null) {
091: result.addAll(e.elements());
092: } else {
093: result.addAll(e.elements(e.getQName()
094: .getDocumentFactory().createQName(localName,
095: "", namespaceUri)));
096: }
097: } else if (node instanceof Document) {
098: Element root = ((Document) node).getRootElement();
099: if (localName == null
100: || (equal(root.getName(), localName) && equal(root
101: .getNamespaceURI(), namespaceUri))) {
102: result.add(root);
103: }
104: }
105: }
106:
107: void getAttributes(Object node, String localName,
108: String namespaceUri, List result) {
109: if (node instanceof Element) {
110: Element e = (Element) node;
111: if (localName == null) {
112: result.addAll(e.attributes());
113: } else {
114: Attribute attr = e.attribute(e.getQName()
115: .getDocumentFactory().createQName(localName,
116: "", namespaceUri));
117: if (attr != null) {
118: result.add(attr);
119: }
120: }
121: } else if (node instanceof ProcessingInstruction) {
122: ProcessingInstruction pi = (ProcessingInstruction) node;
123: if ("target".equals(localName)) {
124: result.add(new DefaultAttribute("target", pi
125: .getTarget()));
126: } else if ("data".equals(localName)) {
127: result.add(new DefaultAttribute("data", pi.getText()));
128: } else {
129: result.add(new DefaultAttribute(localName, pi
130: .getValue(localName)));
131: }
132: } else if (node instanceof DocumentType) {
133: DocumentType doctype = (DocumentType) node;
134: if ("publicId".equals(localName)) {
135: result.add(new DefaultAttribute("publicId", doctype
136: .getPublicID()));
137: } else if ("systemId".equals(localName)) {
138: result.add(new DefaultAttribute("systemId", doctype
139: .getSystemID()));
140: } else if ("elementName".equals(localName)) {
141: result.add(new DefaultAttribute("elementName", doctype
142: .getElementName()));
143: }
144: }
145: }
146:
147: void getDescendants(Object node, List result) {
148: if (node instanceof Branch) {
149: getDescendants((Branch) node, result);
150: }
151: }
152:
153: private void getDescendants(Branch node, List result) {
154: List content = node.content();
155: for (Iterator iter = content.iterator(); iter.hasNext();) {
156: Node subnode = (Node) iter.next();
157: if (subnode instanceof Element) {
158: result.add(subnode);
159: getDescendants(subnode, result);
160: }
161: }
162: }
163:
164: Object getParent(Object node) {
165: return ((Node) node).getParent();
166: }
167:
168: Object getDocument(Object node) {
169: return ((Node) node).getDocument();
170: }
171:
172: Object getDocumentType(Object node) {
173: return node instanceof Document ? ((Document) node)
174: .getDocType() : null;
175: }
176:
177: void getContent(Object node, List result) {
178: if (node instanceof Branch) {
179: result.addAll(((Branch) node).content());
180: }
181: }
182:
183: String getText(Object node) {
184: return ((Node) node).getText();
185: }
186:
187: String getLocalName(Object node) {
188: return ((Node) node).getName();
189: }
190:
191: String getNamespacePrefix(Object node) {
192: if (node instanceof Element) {
193: return ((Element) node).getNamespacePrefix();
194: }
195: if (node instanceof Attribute) {
196: return ((Attribute) node).getNamespacePrefix();
197: }
198: return null;
199: }
200:
201: String getNamespaceUri(Object node) {
202: if (node instanceof Element) {
203: return ((Element) node).getNamespaceURI();
204: }
205: if (node instanceof Attribute) {
206: return ((Attribute) node).getNamespaceURI();
207: }
208: return null;
209: }
210:
211: String getType(Object node) {
212: switch (((Node) node).getNodeType()) {
213: case Node.ATTRIBUTE_NODE: {
214: return "attribute";
215: }
216: case Node.CDATA_SECTION_NODE: {
217: return "cdata";
218: }
219: case Node.COMMENT_NODE: {
220: return "comment";
221: }
222: case Node.DOCUMENT_NODE: {
223: return "document";
224: }
225: case Node.DOCUMENT_TYPE_NODE: {
226: return "documentType";
227: }
228: case Node.ELEMENT_NODE: {
229: return "element";
230: }
231: case Node.ENTITY_REFERENCE_NODE: {
232: return "entityReference";
233: }
234: case Node.NAMESPACE_NODE: {
235: return "namespace";
236: }
237: case Node.PROCESSING_INSTRUCTION_NODE: {
238: return "processingInstruction";
239: }
240: case Node.TEXT_NODE: {
241: return "text";
242: }
243: }
244: return "unknown";
245: }
246:
247: XPathEx createXPathEx(String xpathString)
248: throws TemplateModelException {
249: try {
250: return new Dom4jXPathEx(xpathString);
251: } catch (Exception e) {
252: throw new TemplateModelException(e);
253: }
254: }
255:
256: private static final class Dom4jXPathEx extends Dom4jXPath
257: implements XPathEx {
258: Dom4jXPathEx(String path) throws Exception {
259: super (path);
260: }
261:
262: public List selectNodes(Object object,
263: NamespaceContext namespaces)
264: throws TemplateModelException {
265: Context context = getContext(object);
266: context.getContextSupport().setNamespaceContext(namespaces);
267: try {
268: return selectNodesForContext(context);
269: } catch (Exception e) {
270: throw new TemplateModelException(e);
271: }
272: }
273: }
274: }
|