001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/sam/trunk/component/src/java/org/sakaiproject/tool/assessment/qti/util/XmlUtil.java $
003: * $Id: XmlUtil.java 9274 2006-05-10 22:50:48Z daisyf@stanford.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the"License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.assessment.qti.util;
021:
022: import java.io.FileInputStream;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.net.MalformedURLException;
026: import javax.servlet.ServletContext;
027: import org.springframework.core.io.ClassPathResource;
028:
029: import javax.xml.parsers.DocumentBuilder;
030: import javax.xml.parsers.DocumentBuilderFactory;
031: import javax.xml.parsers.ParserConfigurationException;
032: import javax.xml.transform.Result;
033: import javax.xml.transform.Source;
034: import javax.xml.transform.Transformer;
035: import javax.xml.transform.TransformerConfigurationException;
036: import javax.xml.transform.TransformerException;
037: import javax.xml.transform.TransformerFactory;
038: import javax.xml.transform.dom.DOMResult;
039: import javax.xml.transform.dom.DOMSource;
040:
041: import org.apache.commons.logging.Log;
042: import org.apache.commons.logging.LogFactory;
043: import org.w3c.dom.Document;
044: import org.w3c.dom.NamedNodeMap;
045: import org.w3c.dom.Node;
046: import org.w3c.dom.NodeList;
047: import org.xml.sax.SAXException;
048: import java.io.FileReader;
049: import java.io.Reader;
050: import java.io.BufferedReader;
051: import java.io.ByteArrayInputStream;
052:
053: /**
054: * <p>Copyright: Copyright (c) 2005</p>
055: * <p>Organization: Sakai Project</p>
056: * @author palcasi
057: * mods:
058: * @author Rachel Gollub rgollub@stanford.edu
059: * @author Ed Smiley esmiley@stanford.edu
060: * @version $Id: XmlUtil.java 9274 2006-05-10 22:50:48Z daisyf@stanford.edu $
061: */
062:
063: public final class XmlUtil {
064: private static Log log = LogFactory.getLog(XmlUtil.class);
065:
066: /**
067: * Create document object
068: *
069: * @return Document
070: */
071: public static Document createDocument() {
072: log.debug("createDocument()");
073:
074: Document document = null;
075: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
076: .newInstance();
077: builderFactory.setNamespaceAware(true);
078:
079: try {
080: DocumentBuilder documentBuilder = builderFactory
081: .newDocumentBuilder();
082: document = documentBuilder.newDocument();
083: } catch (ParserConfigurationException e) {
084: log.error(e.getMessage(), e);
085: }
086:
087: return document;
088: }
089:
090: /**
091: * Create document object from XML string
092: *
093: * @return Document
094: */
095: public static Document createDocument(String xmlString) {
096: log.debug("createDocument()");
097:
098: Document document = null;
099: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
100: .newInstance();
101: builderFactory.setNamespaceAware(true);
102:
103: try {
104: DocumentBuilder documentBuilder = builderFactory
105: .newDocumentBuilder();
106: document = documentBuilder.parse(xmlString);
107: } catch (IOException ex) {
108: log.error(ex.getMessage(), ex);
109: } catch (SAXException ex) {
110: log.error(ex.getMessage(), ex);
111: } catch (ParserConfigurationException e) {
112: log.error(e.getMessage(), e);
113: }
114:
115: return document;
116: }
117:
118: /**
119: * Read document from ServletContext/context path
120: *
121: * @param context ServletContext
122: * @param path path
123: *
124: * @return Document
125: */
126: public static Document readDocument(ServletContext context,
127: String path) {
128: if (log.isDebugEnabled()) {
129: log.debug("readDocument(String " + path + ")");
130: }
131:
132: log.debug("readDocument(String " + path + ")");
133:
134: Document document = null;
135: InputStream inputStream = context.getResourceAsStream(path);
136: String fullpath = context.getRealPath(path);
137: log.debug("readDocument(full path) " + fullpath + ")");
138: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
139: .newInstance();
140: builderFactory.setNamespaceAware(true);
141:
142: try {
143: DocumentBuilder documentBuilder = builderFactory
144: .newDocumentBuilder();
145: document = documentBuilder.parse(inputStream);
146: } catch (ParserConfigurationException e) {
147: log.error(e.getMessage(), e);
148: } catch (SAXException e) {
149: log.error(e.getMessage(), e);
150: } catch (IOException e) {
151: log.error(e.getMessage(), e);
152: }
153:
154: return document;
155: }
156:
157: /**
158: * Read document from within spring context path
159: *
160: * @param path path
161: *
162: * @return Document
163: */
164: public static Document readDocument(String path) {
165: if (log.isDebugEnabled()) {
166: log.debug("readDocument(String " + path + ")");
167: }
168:
169: log.debug("readDocument(String " + path + ")");
170:
171: Document document = null;
172: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
173: .newInstance();
174: builderFactory.setNamespaceAware(true);
175: ClassPathResource resource = new ClassPathResource(path);
176:
177: try {
178:
179: InputStream inputStream = resource.getInputStream();
180:
181: DocumentBuilder documentBuilder = builderFactory
182: .newDocumentBuilder();
183: document = documentBuilder.parse(inputStream);
184: } catch (ParserConfigurationException e) {
185: log.error(e.getMessage(), e);
186: } catch (SAXException e) {
187: log.error(e.getMessage(), e);
188: } catch (IOException e) {
189: log.error(e.getMessage(), e);
190: }
191:
192: return document;
193: }
194:
195: public static DOMSource getDocumentSource(ServletContext context,
196: String path) {
197: if (log.isDebugEnabled()) {
198: log.debug("readDocument(String " + path + ")");
199: }
200:
201: InputStream inputStream = context.getResourceAsStream(path);
202: String realPath = null;
203: try {
204: realPath = context.getResource(path).toString();
205: } catch (MalformedURLException e1) {
206: // TODO Auto-generated catch block
207: e1.printStackTrace();
208: }
209: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
210: .newInstance();
211: builderFactory.setNamespaceAware(true);
212:
213: Document document = null;
214: DOMSource source = null;
215: try {
216: DocumentBuilder documentBuilder = builderFactory
217: .newDocumentBuilder();
218: document = documentBuilder.parse(inputStream);
219: source = new DOMSource(document, realPath);
220: } catch (ParserConfigurationException e) {
221: log.error(e.getMessage(), e);
222: } catch (SAXException e) {
223: log.error(e.getMessage(), e);
224: } catch (IOException e) {
225: log.error(e.getMessage(), e);
226: }
227:
228: return source;
229: }
230:
231: /**
232: * direct parse of the file to XML document
233: * @param path the path
234: *
235: * @return a Document
236: */
237: /*
238: public static Document readDocument(String path)
239: {
240: return readDocument(path, false);
241: }
242: */
243: /**
244: * This more forgiving version skips blank lines if trim = true
245: * Otherwise it does a direct parse of the file.
246: * @param path file path
247: * @param trim trim blank lines true/false
248: * @return
249: */
250: public static Document readDocument(String path, boolean trim) {
251: if (log.isDebugEnabled()) {
252: log.debug("readDocument(String " + path + ")");
253: }
254:
255: Document document = null;
256:
257: try {
258: InputStream inputStream;
259:
260: if (trim) {
261: BufferedReader in = new BufferedReader(new FileReader(
262: path));
263:
264: StringBuffer buffer = new StringBuffer();
265: String s = "";
266: while ((s = in.readLine()) != null) {
267: if (s.trim().length() > 0) // skip blank lines
268: {
269: buffer.append(s);
270: buffer.append("\n");
271: }
272: }
273: in.close();
274: byte[] bytes = buffer.toString().getBytes();
275:
276: inputStream = new ByteArrayInputStream(bytes);
277: } else {
278: inputStream = new FileInputStream(path);
279: }
280:
281: DocumentBuilderFactory builderFactory = DocumentBuilderFactory
282: .newInstance();
283: builderFactory.setNamespaceAware(true);
284: DocumentBuilder documentBuilder = builderFactory
285: .newDocumentBuilder();
286: document = documentBuilder.parse(inputStream);
287: } catch (ParserConfigurationException e) {
288: log.error(e.getMessage(), e);
289: } catch (SAXException e) {
290: log.error(e.getMessage(), e);
291: } catch (IOException e) {
292: log.error(e.getMessage(), e);
293: }
294:
295: return document;
296: }
297:
298: /**
299: * Create a transformer from a stylesheet
300: *
301: * @param stylesheet Document
302: *
303: * @return the Transformer
304: */
305: public static Transformer createTransformer(Document stylesheet) {
306:
307: if (log.isDebugEnabled()) {
308: log.debug("createTransformer(Document " + stylesheet + ")");
309: }
310:
311: Transformer transformer = null;
312: TransformerFactory transformerFactory = TransformerFactory
313: .newInstance();
314: URIResolver resolver = new URIResolver();
315: transformerFactory.setURIResolver(resolver);
316:
317: try {
318: DOMSource source = new DOMSource(stylesheet);
319: String systemId = "/xml/xsl/report";
320: source.setSystemId(systemId);
321: transformer = transformerFactory.newTransformer(source);
322: } catch (TransformerConfigurationException e) {
323: log.error(e.getMessage(), e);
324: }
325:
326: return transformer;
327: }
328:
329: /**
330: * Create a transformer from a stylesheet
331: *
332: * @param source DOMSource
333: *
334: * @return the Transformer
335: */
336: public static Transformer createTransformer(DOMSource source) {
337: if (log.isDebugEnabled()) {
338: log.debug("createTransformer(DOMSource " + source + ")");
339: }
340:
341: Transformer transformer = null;
342: TransformerFactory transformerFactory = TransformerFactory
343: .newInstance();
344: URIResolver resolver = new URIResolver();
345: transformerFactory.setURIResolver(resolver);
346:
347: try {
348: transformer = transformerFactory.newTransformer(source);
349: } catch (TransformerConfigurationException e) {
350: log.error(e.getMessage(), e);
351: }
352:
353: return transformer;
354:
355: }
356:
357: /**
358: * Do XSLT transform.
359: *
360: * @param transformer the transsformer
361: * @param source the source
362: * @param result the result
363: */
364: private static void transform(Transformer transformer,
365: Source source, Result result) {
366: if (log.isDebugEnabled()) {
367: log.debug("performTransform(Transformer " + transformer
368: + ", Source" + source + ", Result " + result + ")");
369: }
370:
371: try {
372: transformer.transform(source, result);
373: } catch (TransformerException e) {
374: log.error(e.getMessage(), e);
375: }
376: }
377:
378: /**
379: * Transform one document into another
380: *
381: * @param document source Document
382: * @param stylesheet XSLT Document
383: *
384: * @return transformed Document
385: */
386: public static Document transformDocument(Document document,
387: Document stylesheet) {
388: if (log.isDebugEnabled()) {
389: log.debug("Document transformDocument(Document " + document
390: + ", Document " + stylesheet + ")");
391: }
392: log.debug("Document transformDocument(Document " + document
393: + ", Document " + stylesheet + ")");
394:
395: Document transformedDoc = createDocument();
396: DOMSource docSource = new DOMSource(document);
397: DOMResult docResult = new DOMResult(transformedDoc);
398: Transformer transformer = createTransformer(stylesheet);
399: transform(transformer, docSource, docResult);
400:
401: // log.debug("INPUT DOCUMENT: \n" + (document));
402: // log.debug("TRANSFORM DOCUMENT: \n" + getDOMString(stylesheet));
403: // log.debug("OUTPUT DOCUMENT: \n" + getDOMString(transformedDoc));
404:
405: return transformedDoc;
406: }
407:
408: public static Document transformDocument(Document document,
409: Transformer transformer) {
410:
411: log.debug("Document transformDocument(Document " + document
412: + ", Trasformer " + transformer);
413: Document transformedDoc = createDocument();
414: DOMSource docSource = new DOMSource(document);
415: DOMResult docResult = new DOMResult(transformedDoc);
416: transform(transformer, docSource, docResult);
417:
418: return transformedDoc;
419: }
420:
421: public static void transformNode(Node source, Node result,
422: Transformer transformer) {
423: if (log.isDebugEnabled()) {
424: log.debug("transformNode(Node " + source + ", Node "
425: + result + ", Transformer ," + transformer);
426: }
427: DOMSource domSource = new DOMSource(source);
428: DOMResult domResult = new DOMResult(result);
429: transform(transformer, domSource, domResult);
430: }
431:
432: /**
433: * Get a textual representation of a Node.
434: * @param node The Node
435: * @return the document in a text string
436: */
437: public static String getDOMString(Node node) {
438: String domString = "";
439: int type = node.getNodeType();
440: switch (type) {
441: // print the document element
442: case Node.DOCUMENT_NODE: {
443: domString += "<?xml version=\"1.0\" ?>\n";
444: domString += getDOMString(((Document) node)
445: .getDocumentElement());
446: break;
447: }
448:
449: // print element with attributes
450: case Node.ELEMENT_NODE: {
451: domString += ("<");
452: domString += (node.getNodeName());
453: NamedNodeMap attrs = node.getAttributes();
454: for (int i = 0; i < attrs.getLength(); i++) {
455: Node attr = attrs.item(i);
456: domString += (" " + attr.getNodeName().trim() + "=\""
457: + attr.getNodeValue().trim() + "\"");
458: }
459: domString += (">");
460:
461: NodeList children = node.getChildNodes();
462: if (children != null) {
463: int len = children.getLength();
464: for (int i = 0; i < len; i++)
465: domString += getDOMString(children.item(i));
466: }
467: domString += ("</");
468: domString += (node.getNodeName());
469: domString += (">\n");
470:
471: break;
472: }
473:
474: // handle entity reference nodes
475: case Node.ENTITY_REFERENCE_NODE: {
476: domString += ("&");
477: domString += (node.getNodeName().trim());
478: domString += (";");
479:
480: break;
481: }
482:
483: // print cdata sections
484: case Node.CDATA_SECTION_NODE: {
485: domString += ("");
486: break;
487: }
488:
489: // print text
490: case Node.TEXT_NODE: {
491: String val = node.getNodeValue();
492: if (val == null)
493: val = "";
494: domString += (val);//rshastri .trim() removed SAK-1671
495: break;
496: }
497:
498: // print processing instruction
499: case Node.PROCESSING_INSTRUCTION_NODE: {
500: domString += ("");
501: break;
502: }
503: }
504:
505: if (type == Node.ELEMENT_NODE) {
506: domString += ("\n");
507: }
508:
509: return domString;
510: }
511: }
|