001: /* *****************************************************************************
002: * XMLUtils.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.xml.internal;
011:
012: import java.io.IOException;
013: import java.io.StringReader;
014: import org.jdom.Document;
015: import org.jdom.Element;
016: import org.jdom.output.Format.TextMode;
017: import org.openlaszlo.utils.ChainedException;
018: import org.xml.sax.SAXException;
019:
020: /**
021: * XMLUtils
022: *
023: * @author Oliver Steele
024: */
025: abstract public class XMLUtils {
026: /** Returns an element's attribute value, as a String. Same as
027: * Element.getAttributeValue, except that it takes a default value
028: * to return if the attribute is missing.
029: *
030: * @param e an Element
031: * @param aname the attribute name
032: * @param defaultValue default value
033: * @return a String
034: */
035: public static String getAttributeValue(Element e, String aname,
036: String defaultValue) {
037: String value = e.getAttributeValue(aname);
038: if (value == null) {
039: value = defaultValue;
040: }
041: return value;
042: }
043:
044: /** Returns an element's attribute value, as a String. Same as
045: * Element.getAttributeValue, except guarantees not to return
046: * void.
047: *
048: * @param e an Element
049: * @param aname the attribute name
050: * @return a String
051: */
052: public static String requireAttributeValue(Element e, String aname) {
053: String value = e.getAttributeValue(aname);
054: if (value == null) {
055: throw new MissingAttributeException(e, aname);
056: }
057: return value;
058: }
059:
060: /**
061: * Escape the 5 entities defined by XML.
062: * These are: '<', '>', '\', '&', '"'.
063: *
064: * @param s an xml string
065: * @return an escaped xml string
066: */
067: public static String escapeXml(String s) {
068: if (s == null)
069: return null;
070: StringBuffer sb = new StringBuffer();
071: for (int i = 0; i < s.length(); i++) {
072: char c = s.charAt(i);
073: if (c == '<') {
074: sb.append("<");
075: } else if (c == '>') {
076: sb.append(">");
077: } else if (c == '\'') {
078: sb.append("'");
079: } else if (c == '&') {
080: sb.append("&");
081: } else if (c == '"') {
082: sb.append(""");
083: } else {
084: sb.append(c);
085: }
086: }
087: return sb.toString();
088: }
089:
090: /**
091: * Escape 3 entities understood by HTML text.
092: * These are: '<', '>', '&'
093: *
094: * TODO: [2003-05-05 bloch] move to LZHttpUtils and rename
095: * to escapeHTML
096: *
097: * @param s an xml string
098: * @return an escaped xml string
099: */
100: public static String escapeXmlForSWFHTML(String s) {
101: if (s == null)
102: return null;
103: StringBuffer sb = new StringBuffer();
104: for (int i = 0; i < s.length(); i++) {
105: char c = s.charAt(i);
106: if (c == '<') {
107: sb.append("<");
108: } else if (c == '>') {
109: sb.append(">");
110: } else if (c == '&') {
111: sb.append("&");
112: } else {
113: sb.append(c);
114: }
115: }
116: return sb.toString();
117: }
118:
119: /**
120: * Make sure all the following sequences
121: * < > ' " and &
122: *
123: * have their ampersands escaped
124: *
125: * @param s an xml string
126: * @return an escaped xml string
127: */
128: public static String escapeAmpersands(String s) {
129: if (s == null)
130: return null;
131: StringBuffer sb = new StringBuffer();
132: for (int i = 0; i < s.length(); i++) {
133: char c = s.charAt(i);
134: if (c == '&') {
135: int j = i + 1;
136: if (s.regionMatches(j, "lt;", 0, 3)) {
137: sb.append("&lt;");
138: i += 3;
139: } else if (s.regionMatches(j, "gt;", 0, 3)) {
140: sb.append("&gt;");
141: i += 3;
142: } else if (s.regionMatches(j, "apos;", 0, 5)) {
143: sb.append("&apos;");
144: i += 5;
145: } else if (s.regionMatches(j, "quot;", 0, 5)) {
146: sb.append("&quot;");
147: i += 5;
148: } else if (s.regionMatches(j, "amp;", 0, 4)) {
149: sb.append("&amp;");
150: i += 4;
151: } else {
152: sb.append(c);
153: }
154: } else {
155: sb.append(c);
156: }
157: }
158:
159: return sb.toString();
160: }
161:
162: public static boolean isURL(String str) {
163: // when running in ant, some of these protocols (https and soap, at
164: // least) throw MalformedURLException
165: if (str.startsWith("http:") || str.startsWith("https:")
166: || str.startsWith("file:") || str.startsWith("ftp:")
167: || str.startsWith("soap:")) {
168: return true;
169: }
170: try {
171: new java.net.URL(str); // for effect
172: return true;
173: } catch (java.net.MalformedURLException e) {
174: return false;
175: }
176: }
177:
178: public static Element parse(String source) {
179: try {
180: org.jdom.input.SAXHandler handler = new org.jdom.input.SAXHandler();
181: org.xml.sax.XMLReader reader = org.xml.sax.helpers.XMLReaderFactory
182: .createXMLReader("org.apache.xerces.parsers.SAXParser");
183: reader.setContentHandler(handler);
184: reader.parse(new org.xml.sax.InputSource(new StringReader(
185: source)));
186: Document doc = handler.getDocument();
187: return doc.getRootElement();
188: } catch (IOException e) {
189: throw new ChainedException(e);
190: } catch (SAXException e) {
191: throw new ChainedException(e);
192: }
193: }
194:
195: /**
196: * Returns xml from first non-declaration element.
197: *
198: * @param xml xml string buffer.
199: * @return xml string with no declarations.
200: */
201: public static String getNoDeclarationXML(StringBuffer xml) {
202: int len = xml.length();
203: for (int i = 0; i < len; i++)
204: if (xml.charAt(i) == '<' && (i + 1 < len))
205: if (xml.charAt(i + 1) != '?'
206: && xml.charAt(i + 1) != '!')
207: return xml.substring(i);
208: return xml.toString();
209: }
210:
211: public static String toString(Element element) {
212: org.jdom.output.XMLOutputter outputter = new org.jdom.output.XMLOutputter();
213: outputter.getFormat().setTextMode(TextMode.NORMALIZE);
214: return outputter.outputString(element);
215: }
216:
217: /**
218: * Helper function for getXPathTo
219: */
220: private static StringBuffer getXPathToInternal(Element elt) {
221: Element parent = elt.getParentElement();
222: if (parent == null) {
223: return new StringBuffer("/*[1]");
224: }
225: int i = parent.getChildren().indexOf(elt);
226: if (i == -1) {
227: throw new RuntimeException("Element " + elt
228: + " not in parent " + parent + " .getChildren()?");
229: }
230: StringBuffer sb = getXPathToInternal(parent);
231: sb.append("/*[");
232: // DOM is 1-based
233: sb.append(i + 1);
234: sb.append("]");
235: return sb;
236: }
237:
238: /**
239: * Returns an xpath for the element
240: *
241: * @param elt the element
242: * @return the xpath
243: */
244: public static String getXPathTo(Element elt) {
245: return getXPathToInternal(elt).toString();
246: }
247: }
|