001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: Dom.java 12020 2008-02-19 07:31:46Z lzheng $
023: */
024:
025: package com.bostechcorp.cbesb.common.util;
026:
027: import java.io.ByteArrayInputStream;
028: import java.io.ByteArrayOutputStream;
029: import java.io.File;
030: import java.io.IOException;
031: import java.io.InputStream;
032: import java.io.OutputStream;
033: import java.io.OutputStreamWriter;
034: import java.io.Reader;
035: import java.io.StringWriter;
036:
037: import javax.xml.XMLConstants;
038: import javax.xml.parsers.DocumentBuilder;
039: import javax.xml.parsers.DocumentBuilderFactory;
040: import javax.xml.parsers.ParserConfigurationException;
041: import javax.xml.transform.OutputKeys;
042: import javax.xml.transform.Result;
043: import javax.xml.transform.Source;
044: import javax.xml.transform.Transformer;
045: import javax.xml.transform.TransformerException;
046: import javax.xml.transform.TransformerFactory;
047: import javax.xml.transform.dom.DOMSource;
048: import javax.xml.transform.stream.StreamResult;
049: import javax.xml.validation.SchemaFactory;
050:
051: import org.apache.commons.logging.Log;
052: import org.apache.commons.logging.LogFactory;
053: import org.w3c.dom.Attr;
054: import org.w3c.dom.Document;
055: import org.w3c.dom.Element;
056: import org.w3c.dom.NamedNodeMap;
057: import org.w3c.dom.Node;
058: import org.w3c.dom.NodeList;
059: import org.xml.sax.InputSource;
060: import org.xml.sax.SAXException;
061:
062: import com.sun.org.apache.xpath.internal.NodeSet;
063:
064: public class Dom {
065:
066: protected static transient Log logger = LogFactory
067: .getLog(Dom.class);
068:
069: /**
070: * Create a String result from a DOM document
071: *
072: * @param document
073: * the DOM Document
074: * @return a String representation of the DOM Document
075: * @throws TransformerException
076: */
077: public static String createStringFromDOMDocument(Document document,
078: boolean isXml) throws TransformerException {
079: document.normalize();
080: Source source = new DOMSource(document);
081: StringWriter out = new StringWriter();
082: Result resultStream = new StreamResult(out);
083: TransformerFactory tFactory = TransformerFactory.newInstance();
084: Transformer transformer;
085: transformer = tFactory.newTransformer();
086: if (isXml) {
087: transformer.setOutputProperty(OutputKeys.INDENT, "yes");
088: transformer.setOutputProperty(OutputKeys.METHOD, "xml");
089: }
090: transformer.transform(source, resultStream);
091: String result = out.toString();
092:
093: return result;
094: }
095:
096: /**
097: * Create a String result from a DOM document
098: *
099: * @param document
100: * the DOM Document
101: * @return a String representation of the DOM Document
102: * @throws TransformerException
103: */
104: public static String createStringFromDOMDocumentWithXmlStyle(
105: Document document) throws TransformerException {
106: document.normalize();
107: Source source = new DOMSource(document);
108: StringWriter out = new StringWriter();
109: Result resultStream = new StreamResult(out);
110: TransformerFactory tFactory = TransformerFactory.newInstance();
111: Transformer transformer;
112: transformer = tFactory.newTransformer();
113: transformer.setOutputProperty(OutputKeys.INDENT, "yes");
114: transformer.setOutputProperty(OutputKeys.METHOD, "xml");
115: transformer.transform(source, resultStream);
116: String result = out.toString();
117:
118: return result;
119: }
120:
121: /**
122: * Create a document from a String
123: *
124: * @param xml
125: * xml string
126: * @return document representing the document
127: */
128: public static Document createDocumentFromString(String xml) {
129: Document doc = null;
130: try {
131: DocumentBuilderFactory factory = DocumentBuilderFactory
132: .newInstance();
133: DocumentBuilder builder = factory.newDocumentBuilder();
134: byte[] msgByte = xml.getBytes("utf-8");
135: ByteArrayInputStream in = new ByteArrayInputStream(msgByte);
136: InputSource inputSource = new InputSource(in);
137: doc = builder.parse(inputSource);
138: } catch (Exception e) {
139: logger.error("Exception in createDocumentFromString(): "
140: + e.getMessage());
141: if (logger.isDebugEnabled()) {
142: logger.debug(
143: "Exception in createDocumentFromString():", e);
144: }
145: }
146: return doc;
147: }
148:
149: /**
150: * This function creates a Dom tree from XML file and the XML file gets validated with schemaFile
151: *
152: * @version 1.0
153: *
154: */
155: public synchronized static Document getDomTree(File inFile,
156: File schemaFile) throws SAXException,
157: ParserConfigurationException, IOException {
158: Document domTree = null;
159: DocumentBuilderFactory dbFactory = DocumentBuilderFactory
160: .newInstance();
161:
162: if (schemaFile != null) {
163: SchemaFactory sf = SchemaFactory
164: .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
165: dbFactory.setSchema(sf.newSchema(schemaFile));
166: }
167:
168: DocumentBuilder builder = dbFactory.newDocumentBuilder();
169: dbFactory.setNamespaceAware(true);
170: Node node = builder.parse(inFile);
171: node.normalize();
172: domTree = (Document) node;
173: return domTree;
174: }
175:
176: public synchronized static Document getDomTree(String xml,
177: File schemaFile) throws SAXException,
178: ParserConfigurationException, IOException {
179:
180: return getDomTree(new ByteArrayInputStream(xml
181: .getBytes("utf-8")), schemaFile);
182: }
183:
184: public synchronized static Document getDomTree(InputStream s,
185: File schemaFile) throws SAXException,
186: ParserConfigurationException, IOException {
187: return getDomTree(new InputSource(s), schemaFile);
188: }
189:
190: public synchronized static Document getDomTree(Reader r,
191: File schemaFile) throws SAXException,
192: ParserConfigurationException, IOException {
193: return getDomTree(new InputSource(r), schemaFile);
194: }
195:
196: public synchronized static Document getDomTree(InputSource source,
197: File schemaFile) throws SAXException,
198: ParserConfigurationException, IOException {
199: Document domTree = null;
200: DocumentBuilderFactory dbFactory = DocumentBuilderFactory
201: .newInstance();
202:
203: if (schemaFile != null) {
204: SchemaFactory sf = SchemaFactory
205: .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
206: dbFactory.setSchema(sf.newSchema(schemaFile));
207: }
208:
209: DocumentBuilder builder = dbFactory.newDocumentBuilder();
210: dbFactory.setNamespaceAware(true);
211: Node node = builder.parse(source);
212: node.normalize();
213: domTree = (Document) node;
214: return domTree;
215: }
216:
217: /**
218: * This function creates a new element and adds it to document.
219: *
220: * @version 1.0
221: *
222: */
223:
224: public static Element createElement(Document doc, String elemName)
225: throws Exception {
226: Element currElem = doc.createElement(elemName); // Create element
227:
228: //Append root to doc
229: doc.appendChild(currElem);
230:
231: return currElem;
232: }
233:
234: /**
235: * This function creates a new element and adds it to parentElm.
236: *
237: * @version 1.0
238: *
239: */
240:
241: public static Element createElement(Document doc,
242: Element parentElem, String elemName) throws Exception {
243: Element currElem = doc.createElement(elemName); // Create element
244:
245: //Append root to doc
246: parentElem.appendChild(currElem);
247:
248: return currElem;
249: }
250:
251: /**
252: * This function creates an Attribute
253: *
254: * @version 1.0
255: *
256: */
257:
258: public static void createAttribute(Document doc,
259: Element currentNode, String attrName, String attrValue)
260: throws Exception {
261: Attr attrPointer = null;
262: attrPointer = doc.createAttribute(attrName);
263: if (attrValue != null)
264: attrPointer.setValue(attrValue);
265: else
266: attrPointer.setValue("");
267: currentNode.setAttributeNode(attrPointer);
268: }
269:
270: /**
271: * This function creates a new node and adds it to Parent Element in a given XML document.
272: *
273: * @version 1.0
274: *
275: */
276:
277: public static Element createNode(Document doc, Element parentNode,
278: String nodeName, String nodeValue) throws Exception {
279: Element currentNode = doc.createElement(nodeName); // Create element
280:
281: // if name is not null then create name attribute
282: if (nodeValue != null) {
283: currentNode.appendChild(doc.createTextNode(nodeValue));
284: }
285: // If the node value is null, create an empty node to make sure all elements
286: // have the matching closing XML element
287: else {
288: currentNode.appendChild(doc.createTextNode(""));
289: }
290:
291: //attach element to Root element
292: parentNode.appendChild(currentNode);
293:
294: return currentNode;
295: }
296:
297: /**
298: * Create a String result from a DOM document
299: *
300: * @param document
301: * the DOM Document
302: * @return a String representation of the DOM Document
303: * @throws TransformerException
304: */
305: public static String createStringFromDOMDocument(Document document)
306: throws TransformerException {
307: document.normalize();
308: Source source = new DOMSource(document);
309: StringWriter out = new StringWriter();
310: Result resultStream = new StreamResult(out);
311: TransformerFactory tFactory = TransformerFactory.newInstance();
312: Transformer transformer;
313: transformer = tFactory.newTransformer();
314: transformer.transform(source, resultStream);
315: String result = out.toString();
316:
317: return result;
318: }
319:
320: public static InputStream SourceToInputStream(Source source)
321: throws Exception {
322: ByteArrayOutputStream baos = new ByteArrayOutputStream();
323: StreamResult streamResult = new StreamResult(baos);
324: TransformerFactory factory = TransformerFactory.newInstance();
325: Transformer transformer = factory.newTransformer();
326: transformer.setOutputProperty("encoding", "utf-8");
327: transformer.transform(source, streamResult);
328: return new ByteArrayInputStream(baos.toByteArray());
329: }
330:
331: /**
332: * Create a String result from a DOM Node
333: *
334: * @param node
335: * the DOM Node
336: * @return a String representation of the DOM Document
337: * @throws TransformerException
338: */
339: public static String createStringFromDOMNode(Node node)
340: throws TransformerException {
341: // node.normalize();
342: Source source = new DOMSource(node);
343: StringWriter out = new StringWriter();
344: Result resultStream = new StreamResult(out);
345: TransformerFactory tFactory = TransformerFactory.newInstance();
346: Transformer transformer;
347: transformer = tFactory.newTransformer();
348: transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
349: "yes");
350: transformer.transform(source, resultStream);
351: String result = out.toString();
352: return result;
353: }
354:
355: /**
356: * Search for a child with the given nodeName. If recursive, search in all
357: * the child of firdt level, then if not found, search in the 2nd level of
358: * the first child, ...
359: *
360: * @param parent
361: * parent node
362: * @param nodeName
363: * node name
364: * @param recursive
365: * boolean to know if we got through the xml tree
366: * @return a node
367: */
368: public static Node findChild(Node parent, String nodeName,
369: boolean recursive) {
370: parent.normalize();
371: Node result = null;
372: if (parent != null && nodeName != null) {
373: NodeList nl = parent.getChildNodes();
374: for (int i = 0; i < nl.getLength() && result == null; i++) {
375: if (nodeName.equals(nl.item(i).getNodeName())) {
376: result = nl.item(i);
377: }
378: }
379: // now, search recursively if required
380: if (result == null && recursive) {
381: for (int i = 0; i < nl.getLength() && result == null; i++) {
382: result = findChild(nl.item(i), nodeName, true);
383: }
384: }
385: }
386: return result;
387: }
388:
389: /**
390: * Search for a child with the given nodeName. If recursive, search in all
391: * the child of firdt level, then if not found, search in the 2nd level of
392: * the first child, ...
393: *
394: * @param parent
395: * parent node
396: * @param namespaceURI
397: * The namespaceURI of the node
398: * @param nodeName
399: * node name
400: * @param recursive
401: * boolean to know if we got through the xml tree
402: * @return a node
403: */
404: public static Node findChild(Node parent, String namespaceURI,
405: String nodeName, boolean recursive) {
406: parent.normalize();
407: String prefix = getPrefixForNamespaceURIRecursive(parent,
408: namespaceURI);
409: return (findChild(parent, prefix + nodeName, recursive));
410: }
411:
412: public static NodeList findChildren(Node parent,
413: String namespaceURI, String nodeName, boolean recursive) {
414: parent.normalize();
415: String prefix = getPrefixForNamespaceURIRecursive(parent,
416: namespaceURI);
417: if (prefix != null)
418: return (findChildren(parent, prefix + nodeName, recursive));
419: else
420: return (findChildren(parent, nodeName, recursive));
421:
422: }
423:
424: /**
425: * Search for children with the given nodeName. If recursive, search in all
426: * the children of first level, then search in the 2nd level of the first
427: * children, ...
428: *
429: * @param parent
430: * parent node
431: * @param nodeName
432: * node name
433: * @param recursive
434: * boolean to know if we got through the xml tree
435: * @return a node list of nodes with this name
436: */
437: public static NodeList findChildren(Node parent, String nodeName,
438: boolean recursive) {
439: parent.normalize();
440: NodeSet nodeList = new NodeSet();
441: if (parent != null && nodeName != null) {
442: NodeList nl = parent.getChildNodes();
443: for (int i = 0; i < nl.getLength(); i++) {
444: if (nodeName.equals(nl.item(i).getNodeName())) {
445: nodeList.addElement(nl.item(i));
446: }
447: }
448: // now, search recursively if required
449: if (recursive) {
450: for (int i = 0; i < nl.getLength(); i++) {
451: nodeList = findChildren(nl.item(i), nodeName,
452: nodeList);
453: }
454: }
455: }
456: return nodeList;
457: }
458:
459: /**
460: * Return the value of the attribute in the node
461: *
462: * @param n
463: * the node
464: * @param attName
465: * the name of the attribute
466: * @return the value of the attribute, null if not found
467: */
468: public static String getAttributeValue(Node n, String attName) {
469: NamedNodeMap atts = n.getAttributes();
470: Node att = atts.getNamedItem(attName);
471: if (att != null) {
472: return att.getNodeValue();
473: }
474: return null;
475: }
476:
477: /**
478: * Return the first child of a node, regardless <i>text</i> node
479: *
480: * @param node
481: * @return
482: */
483: public static Node getFirstChild(Node node) {
484: node.normalize();
485: Node result = node.getFirstChild();
486: while (result.getNodeType() == Node.TEXT_NODE) {
487: result = result.getNextSibling();
488: }
489: return result;
490: }
491:
492: /**
493: * Return the next sibling of a node, regardless <i>text</i> node
494: *
495: * @param node
496: * @return
497: */
498: public static Node getNextSibling(Node node) {
499: node.normalize();
500: Node result = node.getNextSibling();
501: while (result.getNodeType() == Node.TEXT_NODE) {
502: result = result.getNextSibling();
503: }
504: return result;
505: }
506:
507: public static NodeList getChildren(Node parent) {
508: parent.normalize();
509: NodeSet nodeList = new NodeSet();
510: if (parent != null) {
511: NodeList nl = parent.getChildNodes();
512: for (int i = 0; i < nl.getLength(); i++) {
513: if (nl.item(i).getNodeType() != Node.TEXT_NODE) {
514: nodeList.addElement(nl.item(i));
515: }
516: }
517: }
518: return nodeList;
519: }
520:
521: /**
522: * Search a document to see if a namespace is declared in it and if it is
523: * returns this namespace URI
524: * @param node
525: * @param namespaceURI
526: * @param deep
527: * @return
528: */
529: public static String getPrefixForNamespaceURI(Node node,
530: String namespaceURI) {
531: String result = "";
532:
533: // Search in root node attributes
534: NamedNodeMap attributes = node.getAttributes();
535: int i = 0;
536: if (attributes != null) {
537: while (i < attributes.getLength()) {
538: Node attr = attributes.item(i++);
539: if (namespaceURI.equals(attr.getNodeValue())) {
540: String nodeName = attr.getNodeName();
541: if (nodeName.startsWith("xmlns:")) {
542: result = nodeName.replaceFirst("xmlns:", "")
543: + ":";
544: return result;
545: } else if (nodeName.startsWith("xmlns")) {
546: return result;
547: }
548: }
549: }
550: }
551: // Search in child nodes attributes
552: i = 0;
553: NodeList nl = node.getChildNodes();
554: while (i < nl.getLength()) {
555: Node tmpNode = nl.item(i++);
556: String prefix = getPrefixForNamespaceURI(tmpNode,
557: namespaceURI);
558: if (prefix != null) {
559: return prefix;
560: }
561: }
562: return null;
563:
564: }
565:
566: public static String getPrefixForNamespaceURIRecursive(Node node,
567: String namespaceURI) {
568: String result = "";
569: if (namespaceURI != null && !"".equals(namespaceURI)) {
570: while (node.getParentNode() != null) {
571: node = node.getParentNode();
572: }
573: // Search in root node attributes
574: NamedNodeMap attributes = node.getAttributes();
575: int i = 0;
576: if (attributes != null) {
577: while (i < attributes.getLength()) {
578: Node attr = attributes.item(i++);
579: if (namespaceURI.equals(attr.getNodeValue())) {
580: String nodeName = attr.getNodeName();
581: if (nodeName.startsWith("xmlns:")) {
582: result = nodeName
583: .replaceFirst("xmlns:", "")
584: + ":";
585: return result;
586: } else if (nodeName.startsWith("xmlns")) {
587: return result;
588: }
589: }
590: }
591: }
592: // Search in child nodes attributes
593: i = 0;
594: NodeList nl = node.getChildNodes();
595: while (i < nl.getLength()) {
596: Node tmpNode = nl.item(i++);
597: String prefix = getPrefixForNamespaceURI(tmpNode,
598: namespaceURI);
599: if (prefix != null) {
600: return prefix;
601: }
602: }
603: }
604:
605: return result;
606: }
607:
608: public static String getNamespaceURIForPrefixRecursive(Node node,
609: String prefix) {
610: String result = "";
611: if (prefix != null) {
612: while (node.getParentNode() != null) {
613: node = node.getParentNode();
614: }
615: // Search in root node attributes
616: NamedNodeMap attributes = node.getAttributes();
617: int i = 0;
618: if (attributes != null) {
619: while (i < attributes.getLength()) {
620: Node attr = attributes.item(i++);
621: String nodeName = attr.getNodeName();
622: if (!"".equals(prefix)
623: && nodeName.startsWith("xmlns:" + prefix)) {
624: return attr.getNodeValue();
625: //here should nameName equals "xmlns", not startWith
626: } else if ("".equals(prefix)
627: && nodeName.equals("xmlns")) {
628: return attr.getNodeValue();
629: }
630: }
631:
632: }
633: // Search in child nodes attributes
634: i = 0;
635: NodeList nl = node.getChildNodes();
636: while (i < nl.getLength()) {
637: Node tmpNode = nl.item(i++);
638: String nameSpaceURI = getNamespaceURIForPrefix(tmpNode,
639: prefix);
640: if (nameSpaceURI != null) {
641: return nameSpaceURI;
642: }
643: }
644: }
645:
646: return result;
647: }
648:
649: public static String getNamespaceURIForPrefix(Node node,
650: String prefix) {
651:
652: // Search in root node attributes
653: NamedNodeMap attributes = node.getAttributes();
654: int i = 0;
655: if (attributes != null) {
656: while (i < attributes.getLength()) {
657: Node attr = attributes.item(i++);
658: String nodeName = attr.getNodeName();
659: if (!"".equals(prefix)
660: && nodeName.startsWith("xmlns:" + prefix)) {
661: return attr.getNodeValue();
662: //here should nameName equals "xmlns", not startWith
663:
664: } else if ("".equals(prefix)
665: && nodeName.equals("xmlns")) {
666: return attr.getNodeValue();
667: }
668:
669: }
670: }
671: // Search in child nodes attributes
672: i = 0;
673: NodeList nl = node.getChildNodes();
674: while (i < nl.getLength()) {
675: Node tmpNode = nl.item(i++);
676: String nameSpaceURI = getNamespaceURIForPrefix(tmpNode,
677: prefix);
678: if (nameSpaceURI != null) {
679: return nameSpaceURI;
680: }
681: }
682: return null;
683:
684: }
685:
686: public static String getPrefix(String nodeName) {
687: if (nodeName.indexOf(":") > -1) {
688: return nodeName.split(":")[0];
689: }
690: return "";
691: }
692:
693: /**
694: * Return the <i>text</i> element of a node
695: *
696: * The implmentation of the DOM3 getTextContent() API Axiom DOM
697: * implementation doesn't support it
698: *
699: *
700: * @param node
701: * @return
702: */
703: public static String getTextContent(Node node) {
704: // node.normalize();
705: // NodeList list = node.getChildNodes();
706: // for (int i = 0; i < list.getLength(); i++) {
707: // if (list.item(i).getNodeType() == Node.TEXT_NODE) {
708: // return list.item(i).getNodeValue();
709: // }
710: // }
711: // return "";
712:
713: StringBuffer sb = new StringBuffer();
714: Node child = node.getFirstChild();
715: while (child != null) {
716: if (child.getNodeType() == Node.TEXT_NODE
717: || child.getNodeType() == Node.CDATA_SECTION_NODE) {
718: sb.append(child.getNodeValue());
719: }
720: child = child.getNextSibling();
721: }
722: return sb.toString();
723: }
724:
725: public static String parseToString(Node node)
726: throws TransformerException {
727: node.normalize();
728: Transformer transformer = TransformerFactory.newInstance()
729: .newTransformer();
730: StringWriter stringWriter = new StringWriter(128);
731: transformer.transform(new DOMSource(node), new StreamResult(
732: stringWriter));
733: StringBuffer buffer = stringWriter.getBuffer();
734: return buffer.toString();
735: }
736:
737: /**
738: * Search recursively for children with the given nodeName.
739: *
740: * @param parent
741: * parent node
742: * @param nodeName
743: * node name
744: * @param nodeList
745: * Set of nodes to be completed
746: * @return a node list of nodes with this name
747: */
748: private static NodeSet findChildren(Node parent, String nodeName,
749: NodeSet nodeList) {
750: if (parent != null && nodeName != null) {
751: NodeList nl = parent.getChildNodes();
752: for (int i = 0; i < nl.getLength(); i++) {
753: if (nodeName.equals(nl.item(i).getNodeName())) {
754: nodeList.addElement(nl.item(i));
755: }
756: }
757: for (int i = 0; i < nl.getLength(); i++) {
758: nodeList = findChildren(nl.item(i), nodeName, nodeList);
759: }
760: }
761: return nodeList;
762: }
763:
764: /**
765: * Write the DOMSource to OutputStream.
766: *
767: * @param src The DOM source.
768: * @param os The OutputStream.
769: * @param charSetName The character set name for encoding.
770: * @throws Exception
771: */
772: public static void writeDOMSource(DOMSource src, OutputStream os,
773: String charSetName) throws Exception {
774: OutputStreamWriter writer = null;
775: if (charSetName == null)
776: writer = new OutputStreamWriter(os);
777: else
778: writer = new OutputStreamWriter(os, charSetName);
779: StreamResult result = new StreamResult(writer);
780: TransformerFactory tf = TransformerFactory.newInstance();
781: Transformer t = tf.newTransformer();
782: t.setOutputProperty(OutputKeys.ENCODING, charSetName);
783: t.setOutputProperty("indent", "yes");
784: t.transform(src, result);
785: writer.close();
786: }
787:
788: }
|