001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.core.domutil;
015:
016: import org.itsnat.impl.core.domutil.ItsNatDOMUtilInternal;
017: import org.w3c.dom.Document;
018: import org.w3c.dom.Element;
019: import org.w3c.dom.Node;
020: import org.w3c.dom.Text;
021:
022: /**
023: * This class provides methods to do frequent DOM related tasks. Most of them
024: * access DOM Element objects filtering/ignoring any other node type.
025: *
026: * @author Jose Maria Arranz Santamaria
027: */
028: public class ItsNatDOMUtil {
029:
030: /**
031: * Returns the first element with the specified id attribute below or the same
032: * as the specified element.
033: *
034: * <p>Use this method when several elements in the tree have the same id attribute
035: * (duplicated id) because <code>Document.getElementById(String)</code> returns the first one. </p>
036: *
037: * @param id the id attribute value to search.
038: * @param container the top most element to search below.
039: * @return the first element object with the specified id or null if not found.
040: */
041: public static Element getElementById(String id, Element container) {
042: /* Este método resuelve el problema de elementos con id duplicado,
043: * permitiendo buscar el elemento en un subconjunto del árbol.
044: */
045: if (id.equals(container.getAttribute("id")))
046: return container;
047: Node child = container.getFirstChild();
048: while (child != null) {
049: if (child.getNodeType() == Node.ELEMENT_NODE) {
050: Element matchElem = getElementById(id, (Element) child);
051: if (matchElem != null)
052: return matchElem;
053: }
054: child = child.getNextSibling();
055: }
056: return null;
057: }
058:
059: /**
060: * Creates a new DOM Element with the specified tag name containing a text node
061: * with the specified text.
062: *
063: * @param tagName the tag name of the new element.
064: * @param text the string contained by the element as a text node, if null or empty no text node is added.
065: * @param doc the document owner of the new element.
066: */
067: public static Element createElement(String tagName, String text,
068: Document doc) {
069: Element elem = doc.createElement(tagName);
070: if ((text != null) && !text.equals(""))
071: elem.appendChild(doc.createTextNode(text));
072: return elem;
073: }
074:
075: /**
076: * Returns the string content of the text node inside the specified Element.
077: *
078: * <p>If the element contains a child node different to a text node a cast exception is thrown.</p>
079: *
080: * @param elem the parent element.
081: * @return the string value of the text child node. If element is empty returns an empty String.
082: */
083: public static String getTextContent(Element elem) {
084: Text textNode = (Text) elem.getFirstChild();
085: if (textNode == null)
086: return ""; // No se puede distinguir entre nulo y vacía
087: return textNode.getData();
088: }
089:
090: /**
091: * Sets the string content of the text node inside the specified Element.
092: *
093: * <p>If the element already contains a text node, then is updated with the
094: * new value. If the new string value is null or empty the child text node is removed.
095: * If first child node is different to a text node a cast exception is thrown.</p>
096: *
097: * @param elem the parent element.
098: * @param value the new string value of the text child node.
099: */
100: public static void setTextContent(Element elem, String value) {
101: if (value == null)
102: value = "";
103: Text textNode = (Text) elem.getFirstChild();
104: if (textNode == null) {
105: if (!value.equals("")) {
106: textNode = elem.getOwnerDocument()
107: .createTextNode(value);
108: elem.appendChild(textNode);
109: }
110: } else if (value.equals(""))
111: elem.removeChild(textNode);
112: else
113: textNode.setData(value);
114: }
115:
116: /**
117: * Removes and returns the content of the specified node.
118: *
119: * <p>If the node is empty returns null. If only contains a child node
120: * returns this child node. If contains more than one child node returns
121: * a <code>DocumentFragment</code> with the child nodes.</p>
122: *
123: * @param parentNode the node to remove the content.
124: * @return a node with the content. May be null a tree node or a <code>DocumentFragment</code>.
125: */
126: public static Node extractChildren(Node parentNode) {
127: Node child = parentNode.getFirstChild();
128: if (child == null)
129: return null;
130: if (child.getNextSibling() == null) {
131: // Es el único, de esta manera nos evitamos crear un DocumentFragment
132: parentNode.removeChild(child);
133: return child;
134: } else {
135: return ItsNatDOMUtilInternal
136: .extractChildrenToDocFragment(parentNode);
137: }
138: }
139:
140: /**
141: * Makes empty the specified node removing all child nodes.
142: *
143: * @param parentNode the node to remove the content.
144: */
145: public static void removeAllChildren(Node parentNode) {
146: Node child = parentNode.getFirstChild();
147: while (child != null) {
148: parentNode.removeChild(child);
149: child = parentNode.getFirstChild();
150: }
151: }
152: }
|