001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.javascript.host;
039:
040: import java.util.ArrayList;
041: import java.util.Iterator;
042: import java.util.List;
043: import java.util.Map;
044:
045: import org.jaxen.JaxenException;
046: import org.mozilla.javascript.Context;
047: import org.mozilla.javascript.NativeArray;
048: import org.mozilla.javascript.Scriptable;
049:
050: import com.gargoylesoftware.htmlunit.html.DomNode;
051: import com.gargoylesoftware.htmlunit.html.HtmlElement;
052: import com.gargoylesoftware.htmlunit.html.xpath.HtmlUnitXPath;
053: import com.gargoylesoftware.htmlunit.javascript.HTMLCollection;
054: import com.gargoylesoftware.htmlunit.xml.XmlAttr;
055: import com.gargoylesoftware.htmlunit.xml.XmlElement;
056:
057: /**
058: * A JavaScript object for XMLElement.
059: *
060: * @version $Revision: 2155 $
061: * @author Ahmed Ashour
062: */
063: public class XMLElement extends Node {
064:
065: private static final long serialVersionUID = 5616690634173934926L;
066:
067: /**
068: * Applies the specified xpath expression to this node's context and returns the generated list of matching nodes.
069: * @param expression A string specifying an XPath expression.
070: * @return list of the found elements.
071: */
072: public HTMLCollection jsxFunction_selectNodes(
073: final String expression) {
074: final HTMLCollection collection = new HTMLCollection(this );
075: try {
076: collection.init(getDomNodeOrDie(), new HtmlUnitXPath(
077: expression));
078: } catch (final JaxenException e) {
079: throw Context
080: .reportRuntimeError("Failed to initialize collection 'selectNodes': "
081: + e.getMessage());
082: }
083: return collection;
084: }
085:
086: /**
087: * Applies the specified pattern-matching operation to this node's context and returns the first matching node.
088: * @param expression A string specifying an XPath expression.
089: * @return the first node that matches the given pattern-matching operation.
090: * If no nodes match the expression, returns a null value.
091: */
092: public Object jsxFunction_selectSingleNode(final String expression) {
093: final HTMLCollection collection = jsxFunction_selectNodes(expression);
094: if (collection.jsxGet_length() > 0) {
095: return collection.get(0, collection);
096: } else {
097: return null;
098: }
099: }
100:
101: /**
102: * Return the tag name of this element.
103: * @return The tag name.
104: */
105: public String jsxGet_tagName() {
106: return ((XmlElement) getDomNodeOrDie()).getTagName();
107: }
108:
109: /**
110: * Returns the attributes of this XML element.
111: * @return the attributes of this XML element.
112: */
113: public Object jsxGet_attributes() {
114: final Map attributes = ((XmlElement) getDomNodeOrDie())
115: .getAttributes();
116: final List list = new ArrayList();
117: for (final Iterator values = attributes.values().iterator(); values
118: .hasNext();) {
119: final XmlAttr attr = (XmlAttr) values.next();
120: list.add(attr.getScriptObject());
121: }
122: return new NativeArray(list.toArray()) {
123: private static final long serialVersionUID = 4370316794526432724L;
124:
125: /**
126: * {@inheritDoc}
127: */
128: public Object get(final String name, final Scriptable start) {
129: for (int i = 0; i < getLength(); i++) {
130: final XMLAttribute attribute = (XMLAttribute) get(
131: i, start);
132: if (attribute.jsxGet_name().equals(name)) {
133: return attribute;
134: }
135: }
136: return super .get(name, start);
137: }
138: };
139: }
140:
141: /**
142: * Gets the specified attribute.
143: * @param attributeName attribute name.
144: * @return The value of the specified attribute, <code>null</code> if the attribute is not defined.
145: */
146: public String jsxFunction_getAttribute(final String attributeName) {
147: final String value = ((XmlElement) getDomNodeOrDie())
148: .getAttributeValue(attributeName);
149: if (value == HtmlElement.ATTRIBUTE_NOT_DEFINED) {
150: return null;
151: } else {
152: return value;
153: }
154: }
155:
156: /**
157: * Set an attribute.
158: *
159: * @param name Name of the attribute to set.
160: * @param value Value to set the attribute to.
161: */
162: public void jsxFunction_setAttribute(final String name,
163: final String value) {
164: ((XmlElement) getDomNodeOrDie()).setAttributeValue(name, value);
165: }
166:
167: /**
168: * Returns all the descendant elements with the specified tag name.
169: * @param tagName the name to search for
170: * @return all the descendant elements with the specified tag name
171: */
172: public Object jsxFunction_getElementsByTagName(final String tagName) {
173: final DomNode domNode = getDomNodeOrDie();
174: final HTMLCollection collection = new HTMLCollection(this );
175: try {
176: final String xpath = "//" + tagName;
177: collection.init(domNode, new HtmlUnitXPath(xpath,
178: HtmlUnitXPath.buildSubtreeNavigator(domNode)));
179: } catch (final JaxenException e) {
180: final String msg = "Error initializing collection getElementsByTagName("
181: + tagName + "): ";
182: throw Context.reportRuntimeError(msg + e.getMessage());
183: }
184: return collection;
185: }
186: }
|