From: <rb...@us...> - 2013-07-17 20:58:35
|
Revision: 8397 http://sourceforge.net/p/htmlunit/code/8397 Author: rbri Date: 2013-07-17 20:58:30 +0000 (Wed, 17 Jul 2013) Log Message: ----------- improving namespace support for XPath expressions; Patch by Chuck Dumont Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/XPathDomNodeList.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/xpath/XPathUtils.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ActiveXObject.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/XPathNSResolver.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocument.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/xml/XmlUtil.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocumentTest.java Added Paths: ----------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NativeFunctionPrefixResolver.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -1369,5 +1369,9 @@ /** Indicates if XUL is supported (FF only). */ @BrowserFeature(@WebBrowser(value = FF, maxVersion = 3.6f)) - XUL_SUPPORT; + XUL_SUPPORT, + + /** Indicates that the 'SelectionNamespaces' property is supported by XPath expressions. */ + @BrowserFeature({ @WebBrowser(IE), @WebBrowser(CHROME) }) + XPATH_SELECTION_NAMESPACES; } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -18,6 +18,7 @@ import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.DOM_NORMALIZE_REMOVE_CHILDREN; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.NODE_APPEND_CHILD_SELF_IGNORE; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.QUERYSELECTORALL_NOT_IN_QUIRKS; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XPATH_SELECTION_NAMESPACES; import java.io.IOException; import java.io.PrintWriter; @@ -26,16 +27,19 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicBoolean; import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; +import org.apache.xml.utils.PrefixResolver; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.CSSParseException; import org.w3c.css.sac.ErrorHandler; @@ -61,6 +65,7 @@ import com.gargoylesoftware.htmlunit.javascript.host.css.CSSStyleSheet; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLDocument; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLElement; +import com.gargoylesoftware.htmlunit.xml.XmlPage; import com.steadystate.css.parser.CSSOMParser; import com.steadystate.css.parser.SACParserCSS3; @@ -83,6 +88,7 @@ * @author Sudhan Moghe * @author <a href="mailto:tom...@un...">Tom Anderson</a> * @author Ronald Brill + * @author Chuck Dumont */ public abstract class DomNode implements Cloneable, Serializable, Node { @@ -1434,6 +1440,29 @@ } /** + * Parses the SelectionNamespaces property into a map of prefix/namespace pairs. + * The default namespace (specified by xmlns=) is placed in the map using the + * empty string ("") key. + * + * @param selectionNS the value of the SelectionNamespaces property + * @return map of prefix/namespace value pairs + */ + private static Map<String, String> parseSelectionNamespaces(final String selectionNS) { + final Map<String, String> result = new HashMap<String, String>(); + final String[] toks = selectionNS.split("\\s"); + for (String tok : toks) { + if (tok.startsWith("xmlns=")) { + result.put("", tok.substring(7, tok.length() - 7)); + } + else if (tok.startsWith("xmlns:")) { + final String prefix[] = tok.substring(6).split("="); + result.put(prefix[0], prefix[1].substring(1, prefix[1].length() - 1)); + } + } + return result.size() > 0 ? result : null; + } + + /** * Evaluates the specified XPath expression from this node, returning the matching elements. * * @param xpathExpr the XPath expression to evaluate @@ -1442,10 +1471,64 @@ * @see #getCanonicalXPath() */ public List<?> getByXPath(final String xpathExpr) { - return XPathUtils.getByXPath(this, xpathExpr); + PrefixResolver prefixResolver = null; + if (hasFeature(XPATH_SELECTION_NAMESPACES)) { + /* + * See if the document has the SelectionNamespaces property defined. If so, then + * create a PrefixResolver that resolves the defined namespaces. + */ + final Document doc = getOwnerDocument(); + if (doc instanceof XmlPage) { + final ScriptableObject scriptable = ((XmlPage) doc).getScriptObject(); + if (ScriptableObject.hasProperty(scriptable, "getProperty")) { + final Object selectionNS = + ScriptableObject.callMethod(scriptable, "getProperty", new Object[]{"SelectionNamespaces"}); + if (selectionNS != null && selectionNS.toString().length() > 0) { + final Map<String, String> namespaces = parseSelectionNamespaces(selectionNS.toString()); + if (namespaces != null) { + prefixResolver = new PrefixResolver() { + @Override + public String getBaseIdentifier() { + return namespaces.get(""); + } + + @Override + public String getNamespaceForPrefix(final String prefix) { + return namespaces.get(prefix); + } + + @Override + public String getNamespaceForPrefix(final String prefix, final Node node) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean handlesNullPrefixes() { + return false; + } + }; + } + } + } + } + } + return XPathUtils.getByXPath(this, xpathExpr, prefixResolver); } /** + * Evaluates the specified XPath expression from this node, returning the matching elements. + * + * @param xpathExpr the XPath expression to evaluate + * @param resolver the prefix resolver to use for resolving namespace prefixes, or null + * @return the elements which match the specified XPath expression + * @see #getFirstByXPath(String) + * @see #getCanonicalXPath() + */ + public List<?> getByXPath(final String xpathExpr, final PrefixResolver resolver) { + return XPathUtils.getByXPath(this, xpathExpr, resolver); + } + + /** * Evaluates the specified XPath expression from this node, returning the first matching element, * or <tt>null</tt> if no node matches the specified XPath expression. * @@ -1455,9 +1538,24 @@ * @see #getByXPath(String) * @see #getCanonicalXPath() */ + public <X> X getFirstByXPath(final String xpathExpr) { + return getFirstByXPath(xpathExpr, null); + } + + /** + * Evaluates the specified XPath expression from this node, returning the first matching element, + * or <tt>null</tt> if no node matches the specified XPath expression. + * + * @param xpathExpr the XPath expression + * @param <X> the expression type + * @param resolver the prefix resolver to use for resolving namespace prefixes, or null + * @return the first element matching the specified XPath expression + * @see #getByXPath(String) + * @see #getCanonicalXPath() + */ @SuppressWarnings("unchecked") - public <X> X getFirstByXPath(final String xpathExpr) { - final List<?> results = getByXPath(xpathExpr); + public <X> X getFirstByXPath(final String xpathExpr, final PrefixResolver resolver) { + final List<?> results = getByXPath(xpathExpr, resolver); if (results.isEmpty()) { return null; } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/XPathDomNodeList.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/XPathDomNodeList.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/XPathDomNodeList.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -84,7 +84,7 @@ private List<Object> getNodes() { if (cachedElements_ == null) { if (node_ != null) { - cachedElements_ = XPathUtils.getByXPath(node_, xpath_); + cachedElements_ = XPathUtils.getByXPath(node_, xpath_, null); } else { cachedElements_ = new ArrayList<Object>(); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/xpath/XPathUtils.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/xpath/XPathUtils.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/xpath/XPathUtils.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -37,6 +37,7 @@ * * @version $Revision$ * @author Ahmed Ashour + * @author Chuck Dumont */ public final class XPathUtils { @@ -59,9 +60,10 @@ * * @param node the node to start searching from * @param xpathExpr the XPath expression + * @param resolver the prefix resolver to use for resolving namespace prefixes, or null * @return the list of objects found */ - public static List<Object> getByXPath(final DomNode node, final String xpathExpr) { + public static List<Object> getByXPath(final DomNode node, final String xpathExpr, final PrefixResolver resolver) { if (xpathExpr == null) { throw new NullPointerException("Null is not a valid XPath expression"); } @@ -69,7 +71,7 @@ PROCESS_XPATH_.set(Boolean.TRUE); final List<Object> list = new ArrayList<Object>(); try { - final XObject result = evaluateXPath(node, xpathExpr); + final XObject result = evaluateXPath(node, xpathExpr, resolver); if (result instanceof XNodeSet) { final NodeList nodelist = ((XNodeSet) result).nodelist(); @@ -111,10 +113,12 @@ * Evaluates an XPath expression to an XObject. * @param contextNode the node to start searching from * @param str a valid XPath string + * @param a prefix resolver to use for resolving namespace prefixes, or null * @return an XObject, which can be used to obtain a string, number, nodelist, etc (should never be <tt>null</tt>) * @throws TransformerException if a syntax or other error occurs */ - private static XObject evaluateXPath(final DomNode contextNode, final String str) throws TransformerException { + private static XObject evaluateXPath(final DomNode contextNode, + final String str, final PrefixResolver prefixResolver) throws TransformerException { final XPathContext xpathSupport = new XPathContext(); final Node xpathExpressionContext; if (contextNode.getNodeType() == Node.DOCUMENT_NODE) { @@ -123,9 +127,14 @@ else { xpathExpressionContext = contextNode; } - final PrefixResolver prefixResolver = new HtmlUnitPrefixResolver(xpathExpressionContext); + + PrefixResolver resolver = prefixResolver; + if (resolver == null) { + resolver = new HtmlUnitPrefixResolver(xpathExpressionContext); + } + final boolean caseSensitive = contextNode.getPage().hasCaseSensitiveTagNames(); - final XPathAdapter xpath = new XPathAdapter(str, null, prefixResolver, null, caseSensitive); + final XPathAdapter xpath = new XPathAdapter(str, null, resolver, null, caseSensitive); final int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode); return xpath.execute(xpathSupport, ctxtNode, prefixResolver); } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ActiveXObject.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ActiveXObject.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/ActiveXObject.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -51,6 +51,7 @@ * @version $Revision$ * @author <a href="mailto:bc...@es...">Ben Curren</a> * @author Ahmed Ashour + * @author Chuck Dumont */ @JsxClass(browsers = @WebBrowser(IE)) public class ActiveXObject extends SimpleScriptable { @@ -230,6 +231,7 @@ addFunction(document, "createCDATASection"); addFunction(document, "createProcessingInstruction"); addFunction(document, "getElementsByTagName"); + addFunction(document, "getProperty"); addFunction(document, "load"); addFunction(document, "loadXML"); addFunction(document, "nodeFromID"); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/Document.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -26,9 +26,11 @@ import java.util.regex.Pattern; import net.sourceforge.htmlunit.corejs.javascript.Context; +import net.sourceforge.htmlunit.corejs.javascript.NativeFunction; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xml.utils.PrefixResolver; import com.gargoylesoftware.htmlunit.BrowserVersion; import com.gargoylesoftware.htmlunit.BrowserVersionFeatures; @@ -73,6 +75,7 @@ * @author Ahmed Ashour * @author Rob Di Marco * @author Ronald Brill + * @author Chuck Dumont * @see <a href="http://msdn.microsoft.com/en-us/library/ms531073.aspx">MSDN documentation</a> * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-7068919">W3C Dom Level 1</a> */ @@ -393,7 +396,15 @@ xPathResult.setParentScope(getParentScope()); xPathResult.setPrototype(getPrototype(xPathResult.getClass())); } - xPathResult.init(contextNode.getDomNodeOrDie().getByXPath(expression), type); + + PrefixResolver prefixResolver = null; + if (resolver instanceof NativeFunction) { + prefixResolver = new NativeFunctionPrefixResolver((NativeFunction) resolver, contextNode.getParentScope()); + } + else if (resolver instanceof PrefixResolver) { + prefixResolver = (PrefixResolver) resolver; + } + xPathResult.init(contextNode.getDomNodeOrDie().getByXPath(expression, prefixResolver), type); return xPathResult; } Added: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NativeFunctionPrefixResolver.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NativeFunctionPrefixResolver.java (rev 0) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NativeFunctionPrefixResolver.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2013 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gargoylesoftware.htmlunit.javascript.host; + +import net.sourceforge.htmlunit.corejs.javascript.Context; +import net.sourceforge.htmlunit.corejs.javascript.NativeFunction; +import net.sourceforge.htmlunit.corejs.javascript.Scriptable; + +import org.apache.xml.utils.PrefixResolver; + +/** + * A special {@link PrefixResolver} for {@link NativeFunction}s. + * + * @version $Revision$ + * @author Chuck Dumont + */ +public class NativeFunctionPrefixResolver implements PrefixResolver { + + private NativeFunction resolverFn_; + private Scriptable scope_; + + /** + * Constructor. + * + * @param resolverFn the {@link NativeFunction} this resolver is for + * @param scope the scope + */ + public NativeFunctionPrefixResolver(final NativeFunction resolverFn, final Scriptable scope) { + resolverFn_ = resolverFn; + scope_ = scope; + } + + /** + * {@inheritDoc} + */ + @Override + public String getBaseIdentifier() { + final Object result = Context.call(null, resolverFn_, scope_, null, new Object[]{}); + return result != null ? result.toString() : null; + } + + /** + * {@inheritDoc} + */ + @Override + public String getNamespaceForPrefix(final String prefix) { + final Object result = Context.call(null, resolverFn_, scope_, null, new Object[]{prefix}); + return result != null ? result.toString() : null; + } + + /** + * {@inheritDoc} + */ + @Override + public String getNamespaceForPrefix(final String prefix, final org.w3c.dom.Node node) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean handlesNullPrefixes() { + return false; + } +} Property changes on: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/NativeFunctionPrefixResolver.java ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +Author Date Id Revision \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/XPathNSResolver.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/XPathNSResolver.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/XPathNSResolver.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -16,6 +16,8 @@ import static com.gargoylesoftware.htmlunit.javascript.configuration.BrowserName.FF; +import org.apache.xml.utils.PrefixResolver; + import com.gargoylesoftware.htmlunit.html.DomElement; import com.gargoylesoftware.htmlunit.javascript.SimpleScriptable; import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass; @@ -28,9 +30,10 @@ * * @version $Revision$ * @author Ahmed Ashour + * @author Chuck Dumont */ @JsxClass(browsers = @WebBrowser(FF)) -public class XPathNSResolver extends SimpleScriptable { +public class XPathNSResolver extends SimpleScriptable implements PrefixResolver { private Object element_; @@ -53,4 +56,35 @@ return XmlUtil.lookupNamespaceURI((DomElement) ((SimpleScriptable) element_).getDomNodeOrDie(), prefix); } + /** + * {@inheritDoc} + */ + @Override + public String getBaseIdentifier() { + return XmlUtil.lookupNamespaceURI((DomElement) ((SimpleScriptable) element_).getDomNodeOrDie(), ""); + } + + /** + * {@inheritDoc} + */ + @Override + public String getNamespaceForPrefix(final String prefix) { + return lookupNamespaceURI(prefix); + } + + /** + * {@inheritDoc} + */ + @Override + public String getNamespaceForPrefix(final String prefix, final org.w3c.dom.Node context) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean handlesNullPrefixes() { + return false; + } } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocument.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocument.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocument.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -21,7 +21,9 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import net.sourceforge.htmlunit.corejs.javascript.Context; @@ -60,6 +62,7 @@ * @author Marc Guillemot * @author Sudhan Moghe * @author Ronald Brill + * @author Chuck Dumont */ @JsxClass(browsers = @WebBrowser(FF)) public class XMLDocument extends Document { @@ -69,6 +72,7 @@ private boolean async_ = true; private boolean preserveWhiteSpace_; private XMLDOMParseError parseError_; + private Map<String, String> properties_ = new HashMap<String, String>(); /** * Creates a new instance. JavaScript objects must have a default constructor. @@ -266,10 +270,21 @@ */ @JsxFunction({ @WebBrowser(IE), @WebBrowser(CHROME) }) public void setProperty(final String name, final String value) { - //empty implementation + properties_.put(name, value); } /** + * Returns the value of the property set by {@link #setProperty(String, String)}. + * + * @param name the name of the property to get + * @return the property value + */ + @JsxFunction({ @WebBrowser(IE), @WebBrowser(CHROME) }) + public String getProperty(final String name) { + return properties_.get(name); + } + + /** * Applies the specified XPath expression to this node's context and returns the generated list of matching nodes. * @param expression a string specifying an XPath expression * @return list of the found elements Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/xml/XmlUtil.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/xml/XmlUtil.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/xml/XmlUtil.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -65,6 +65,7 @@ * @author Ahmed Ashour * @author Sudhan Moghe * @author Ronald Brill + * @author Chuck Dumont */ public final class XmlUtil { @@ -301,12 +302,19 @@ /** * Search for the namespace URI of the given prefix, starting from the specified element. + * The default namespace can be searched for by specifying "" as the prefix. * @param element the element to start searching from * @param prefix the namespace prefix * @return the namespace URI bound to the prefix; or null if there is no such namespace */ public static String lookupNamespaceURI(final DomElement element, final String prefix) { - String uri = element.getAttribute("xmlns:" + prefix); + String uri = DomElement.ATTRIBUTE_NOT_DEFINED; + if (prefix.length() == 0) { + uri = element.getAttribute("xmlns"); + } + else { + uri = element.getAttribute("xmlns:" + prefix); + } if (uri == DomElement.ATTRIBUTE_NOT_DEFINED) { final DomNode parentNode = element.getParentNode(); if (parentNode instanceof DomElement) { Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocumentTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocumentTest.java 2013-07-17 05:20:45 UTC (rev 8396) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/host/xml/XMLDocumentTest.java 2013-07-17 20:58:30 UTC (rev 8397) @@ -34,6 +34,7 @@ * @version $Revision$ * @author Ahmed Ashour * @author Marc Guillemot + * @author Chuck Dumont */ @RunWith(BrowserRunner.class) public class XMLDocumentTest extends WebDriverTestCase { @@ -695,7 +696,6 @@ */ @Test @Alerts(IE = "1", FF = "0") - @NotYetImplemented(IE) public void xpathWithNamespaces() throws Exception { final String html = "<html><head><title>foo</title><script>\n" + " function test() {\n" @@ -703,7 +703,7 @@ + " doc.async = false;\n" + " doc.load('" + URL_SECOND + "');\n" + " try {\n" - + " alert(doc.selectNodes('//book').length);\n" + + " alert(doc.selectNodes('//soap:book').length);\n" + " } catch (e) {\n" + " alert(doc.evaluate('count(//book)', doc.documentElement, " + "null, XPathResult.NUMBER_TYPE, null).numberValue);\n" @@ -736,6 +736,46 @@ * @throws Exception if the test fails */ @Test + @Browsers(IE) + @Alerts("1") + public void selectionNamespaces() throws Exception { + final String html = "<html><head><title>foo</title><script>\n" + + " var selectionNamespaces = 'xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " + + "xmlns:ns1=\"http://www.example.com/ns1\"';\n" + + " function test() {\n" + + " if (window.ActiveXObject) {" + + " var doc = new ActiveXObject('Microsoft.XMLDOM');\n" + + " doc.setProperty('SelectionNamespaces', selectionNamespaces);" + + " doc.async = false;\n" + + " doc.load('" + URL_SECOND + "');\n" + + " try {\n" + + " alert(doc.selectNodes('/s:Envelope/ns1:books/s:book').length);\n" + + " } catch (e) {\n" + + " alert(doc.evaluate('count(//book)', doc.documentElement, " + + "null, XPathResult.NUMBER_TYPE, null).numberValue);\n" + + " }}\n" + + " }\n" + + "</script></head><body onload='test()'>\n" + + "</body></html>"; + + final String xml + = "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>\n" + + " <books xmlns='http://www.example.com/ns1'>\n" + + " <soap:book>\n" + + " <title>Immortality</title>\n" + + " <author>John Smith</author>\n" + + " </soap:book>\n" + + " </books>\n" + + "</soap:Envelope>"; + + getMockWebConnection().setResponse(URL_SECOND, xml, "text/xml"); + loadPageWithAlerts2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts(IE = "null", FF = "[object HTMLDivElement]") public void nodeFromID() throws Exception { final String html = "<html><head><title>foo</title><script>\n" |