From: Manolo Carrasco Date: Wed, 2 Jun 2010 07:53:39 +0000 (+0000) Subject: resolved an issue related to the context where a xpath selector produced with Css2Xpa... X-Git-Tag: release-1.3.2~707 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=0daa529f77eba8502556724b363988b2bb4b929e;p=gwtquery.git resolved an issue related to the context where a xpath selector produced with Css2Xpath was executed, and another problem with the handle of attributes when the tag was not given, and fixed the tests --- diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java index 3e3d482b..c3c72a74 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java @@ -60,9 +60,21 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl { } }; + private static ReplaceCallback rc_Attr = new ReplaceCallback() { + public String foundMatch(ArrayList s) { + if (s.get(1) == null || s.get(1).length() == 0) { + s.set(1, "*"); + } + if (s.get(3) == null || s.get(3).length() == 0) { + s.set(3, ""); + } + return s.get(1) + "[@" + s.get(2) + s.get(3) + "]"; + } + }; + private static ReplaceCallback rc_nth_child = new ReplaceCallback() { public String foundMatch(ArrayList s) { - if (s.get(1).length() == 0) { + if (s.get(1) == null || s.get(1).length() == 0) { s.set(1, "0"); } if ("n".equals(s.get(2))) { @@ -82,7 +94,8 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl { }; private static Object[] regs = new Object[]{ - "\\[([^\\]~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]", "[@$1$2]", + // tag[attrib=value] + "([a-zA-Z0-9_\\-\\*\\[\\]])?\\[([^\\]@~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]", rc_Attr, // multiple queries "\\s*,\\s*", "|", // , + ~ > @@ -98,9 +111,7 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl { "([\\>\\+\\|\\~\\,\\s])([a-zA-Z\\*]+)", "$1//$2", "\\s+//", "//", // :first-child - "([a-zA-Z0-9_\\-\\*]+):first-child", "*[1]/self::$1", - // :first - "([a-zA-Z0-9_\\-\\*]+):first", "*[1]/self::$1", + "([a-zA-Z0-9_\\-\\*]+):first-child", "$1[not(preceding-sibling::*)]", // :last-child "([a-zA-Z0-9_\\-\\*]+):last-child", "$1[not(following-sibling::*)]", // :only-child @@ -127,7 +138,10 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl { "#([a-zA-Z0-9_\\-]+)", "[@id='$1']", "\\.([a-zA-Z0-9_\\-]+)", "[contains(concat(' ',normalize-space(@class),' '),' $1 ')]", // normalize multiple filters - "\\]\\[([^\\]]+)", " and ($1)"}; + "\\]\\[([^\\]]+)", " and ($1)", + // tag:attrib + "([a-zA-Z0-9_\\-\\*]+):([a-zA-Z0-9_\\-]+)", "$1[@$2='$2']" + }; public static SelectorEngineCssToXPath getInstance() { if (instance == null) { @@ -173,12 +187,12 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl { for (int i = 0; i < regs.length;) { ret = replacer.replaceAll(ret, regs[i++].toString(), regs[i++]); } - return "//" + ret; + return ".//" + ret; } public NodeList select(String sel, Node ctx) { JSArray elm = JSArray.create(); - if (!sel.startsWith("//") && !sel.startsWith("./") && !sel.startsWith("/")) { + if (!sel.startsWith("./") && !sel.startsWith("/")) { sel = css2Xpath(sel); } SelectorEngine.xpathEvaluate(sel, ctx, elm); diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java index 0b07abc5..afbaaa14 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java @@ -15,6 +15,7 @@ */ package com.google.gwt.query.client.impl; +import com.google.gwt.core.client.JsArray; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; @@ -369,7 +370,7 @@ public class SelectorEngineJS extends SelectorEngineImpl { elm.pushAll(prevElem); } - return elm; + return unique(elm.>cast()).cast(); } protected String getAttr(Element current, String name) { diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java index 45b52f2b..578ce977 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java @@ -18,6 +18,7 @@ package com.google.gwt.query.client.impl; import static com.google.gwt.query.client.SelectorEngine.eq; import static com.google.gwt.query.client.SelectorEngine.truth; +import com.google.gwt.core.client.JsArray; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; @@ -59,8 +60,6 @@ public class SelectorEngineXPath extends SelectorEngineImpl { private Regexp combinator; - private SelectorEngineImpl jsEngine = null; - public SelectorEngineXPath() { } @@ -140,16 +139,9 @@ public class SelectorEngineXPath extends SelectorEngineImpl { } } } - try { - SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm).cast(); - } catch (Exception e) { - if (jsEngine == null) { - jsEngine = new SelectorEngineSizzle(); - } - return jsEngine.select(sel, ctx).cast(); - } + SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm); } - return elm; + return unique(elm.>cast()).cast(); } private void init() { diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTest.java index 7bbc438e..4b730e7c 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTest.java @@ -24,6 +24,7 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.query.client.impl.SelectorEngineCssToXPath; import com.google.gwt.query.client.impl.SelectorEngineImpl; import com.google.gwt.query.client.impl.SelectorEngineJS; import com.google.gwt.query.client.impl.SelectorEngineNative; @@ -208,11 +209,18 @@ public class GQuerySelectorsTest extends GWTTestCase { public void testIssue12() { $(e).html("

1

2
"); - executeSelectInAllImplementations("[myCustomAttr]", 2); - executeSelectInAllImplementations("*[myCustomAttr]", 2); - executeSelectInAllImplementations("input[name=wantedName]", 1); - executeSelectInAllImplementations("input[name='wantedName']", 1); - executeSelectInAllImplementations("input[name=\"wantedName\"]", 1); + executeSelectInAllImplementations("[myCustomAttr]", e, 2); + executeSelectInAllImplementations("*[myCustomAttr]", e, 2); + executeSelectInAllImplementations("input[name=wantedName]", e, 1); + executeSelectInAllImplementations("input[name='wantedName']", e, 1); + executeSelectInAllImplementations("input[name=\"wantedName\"]", e, 1); + } + + public void testSelectElementsInsideContext() { + $(e).html("

s

"); + GQuery q = $("spam", e); + // TODO: in XPath engine it returns 2 when it should return 1 + executeSelectInAllImplementations("*", q.get(0), 1, 2); } public void testSelectorEngineDomAssistant() { @@ -231,6 +239,11 @@ public class GQuerySelectorsTest extends GWTTestCase { executeSelectorEngineTests(selEng); } + public void testSelectorEngineCssToXpath() { + SelectorEngineImpl selEng = new SelectorEngineCssToXPath(); + executeSelectorEngineTests(selEng); + } + public void testSelectorsGeneratorNative() { $(e).html( "1" @@ -304,16 +317,18 @@ public class GQuerySelectorsTest extends GWTTestCase { assertTrue(message, done); } - private void executeSelectInAllImplementations(String selector, int result) { + private void executeSelectInAllImplementations(String selector, Element elem, Object... array) { SelectorEngineImpl selSizz = new SelectorEngineSizzle(); SelectorEngineImpl selJS = new SelectorEngineJS(); SelectorEngineImpl selXpath = new SelectorEngineXPath(); + SelectorEngineImpl selC2X = new SelectorEngineCssToXPath(); SelectorEngineImpl selNative = new SelectorEngineNative(); - assertEquals(result, selSizz.select(selector, e).getLength()); - assertEquals(result, selJS.select(selector, e).getLength()); - assertEquals(result, selXpath.select(selector, e).getLength()); + assertArrayContains(selector, selSizz.select(selector, elem).getLength(), array); + assertArrayContains(selector, selJS.select(selector, elem).getLength(), array); + assertArrayContains(selector, selXpath.select(selector, elem).getLength(), array); + assertArrayContains(selector, selC2X.select(selector, elem).getLength(), array); if (hasNativeSelector()) { - assertEquals(result, selNative.select(selector, e).getLength()); + assertArrayContains(selector, selNative.select(selector, elem), array); } } @@ -328,6 +343,7 @@ public class GQuerySelectorsTest extends GWTTestCase { assertArrayContains(selEng.select("body div", Document.get()).getLength(), 53, 55); assertArrayContains(selEng.select("h1[id]:contains(Selectors)", e).getLength(), 1); + // :first is not a valid selector, it only works in sizzle assertArrayContains(selEng.select("*:first", e).getLength(), 1, 0); assertArrayContains(selEng.select("div[class!=madeup]", e).getLength(), 52, 53); assertArrayContains(selEng.select("div, p a", e).getLength(), 136, 137, 138); @@ -362,7 +378,7 @@ public class GQuerySelectorsTest extends GWTTestCase { assertArrayContains(selEng.select("p:nth-child(odd)", e).getLength(), 165); assertArrayContains(selEng.select("p:only-child", e).getLength(), 3); assertArrayContains(selEng.select("#title", e).getLength(), 1); - assertArrayContains(selEng.select("#title, h1#title", e).getLength(), 2); + assertArrayContains(selEng.select("#title, h1#title", e).getLength(), 1); assertArrayContains(selEng.select("ul.toc li.tocline2", e).getLength(), 12); assertArrayContains(selEng.select("h1[id]:contains(Selectors)", e).getLength(), 1); } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java index 43d15416..1f4f3e27 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java @@ -29,26 +29,35 @@ public class SelectorEnginesTest extends GWTTestCase { public void testCssToXpath() { SelectorEngineCssToXPath sel = new SelectorEngineCssToXPath(); - assertEquals("//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", + assertEquals(".//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", sel.css2Xpath("div[class^=exa][class$=mple]")); - assertEquals("//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", + assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); - assertEquals("//p", + assertEquals(".//p", sel.css2Xpath("p:nth-child(n)")); - assertEquals("//p[(count(preceding-sibling::*) + 1) mod 2=1]", + assertEquals(".//p[(count(preceding-sibling::*) + 1) mod 2=1]", sel.css2Xpath("p:nth-child(odd)")); - assertEquals("//*[(position()-0) mod 2=0 and position()>=0]/self::p", + assertEquals(".//*[(position()-0) mod 2=0 and position()>=0]/self::p", sel.css2Xpath("p:nth-child(2n)")); - assertEquals("//div[substring(@class,string-length(@class)-3)='mple']", + assertEquals(".//div[substring(@class,string-length(@class)-3)='mple']", sel.css2Xpath("div[class$=mple]")); - assertEquals("//div[substring(@class,string-length(@class)-5)='xample']", + assertEquals(".//div[substring(@class,string-length(@class)-5)='xample']", sel.css2Xpath("div[class$=xample]")); - assertEquals("//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", + assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); + assertEquals(".//*[@myAttr]", + sel.css2Xpath("[myAttr]")); + + assertEquals(".//tag[@myAttr='abcd']", + sel.css2Xpath("tag[myAttr=abcd]")); + + assertEquals(".//a[@href and (@lang) and (@class)]", + sel.css2Xpath("a[href][lang][class]")); + } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java index 4f605797..1ace9d52 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java @@ -32,25 +32,41 @@ public class SelectorGeneratorsTest extends GWTTestCase { public void testCss2Xpath() { SelectorGeneratorCssToXPath sel = new SelectorGeneratorCssToXPath(); - assertEquals("//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", + assertEquals(".//div[starts-with(@class,'exa') and (substring(@class,string-length(@class)-3)='mple')]", sel.css2Xpath("div[class^=exa][class$=mple]")); - assertEquals("//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", + assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); - assertEquals("//p", + assertEquals(".//p", sel.css2Xpath("p:nth-child(n)")); - assertEquals("//p[(count(preceding-sibling::*) + 1) mod 2=1]", + assertEquals(".//p[(count(preceding-sibling::*) + 1) mod 2=1]", sel.css2Xpath("p:nth-child(odd)")); - assertEquals("//*[(position()-0) mod 2=0 and position()>=0]/self::p", + assertEquals(".//*[(position()-0) mod 2=0 and position()>=0]/self::p", sel.css2Xpath("p:nth-child(2n)")); - assertEquals("//div[substring(@class,string-length(@class)-3)='mple']", + assertEquals(".//div[substring(@class,string-length(@class)-3)='mple']", sel.css2Xpath("div[class$=mple]")); - assertEquals("//div[substring(@class,string-length(@class)-5)='xample']", + assertEquals(".//div[substring(@class,string-length(@class)-5)='xample']", sel.css2Xpath("div[class$=xample]")); - assertEquals("//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", + assertEquals(".//div[not(contains(concat(' ',normalize-space(@class),' '),' example '))]", sel.css2Xpath("div:not(.example)")); + + assertEquals(".//*", + sel.css2Xpath("*")); + + assertEquals(".//input[@checked='checked']", + sel.css2Xpath("input:checked")); + + assertEquals(".//*[@myAttr]", + sel.css2Xpath("[myAttr]")); + + assertEquals(".//tag[@myAttr='abcd']", + sel.css2Xpath("tag[myAttr=abcd]")); + + assertEquals(".//a[@href and (@lang) and (@class)]", + sel.css2Xpath("a[href][lang][class]")); + } public void testReplaceAll() {