]> source.dussan.org Git - gwtquery.git/commitdiff
resolved an issue related to the context where a xpath selector produced with Css2Xpa...
authorManolo Carrasco <manolo@apache.org>
Wed, 2 Jun 2010 07:53:39 +0000 (07:53 +0000)
committerManolo Carrasco <manolo@apache.org>
Wed, 2 Jun 2010 07:53:39 +0000 (07:53 +0000)
gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineCssToXPath.java
gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineJS.java
gwtquery-core/src/main/java/com/google/gwt/query/client/impl/SelectorEngineXPath.java
gwtquery-core/src/test/java/com/google/gwt/query/client/GQuerySelectorsTest.java
gwtquery-core/src/test/java/com/google/gwt/query/client/impl/SelectorEnginesTest.java
gwtquery-core/src/test/java/com/google/gwt/query/rebind/SelectorGeneratorsTest.java

index 3e3d482bbb4b9095b74c6562f62a83bfe8796ce3..c3c72a74150d6b01977f259fde8cfd74c12b7443 100644 (file)
@@ -60,9 +60,21 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl {
     }\r
   };\r
   \r
+  private static ReplaceCallback rc_Attr = new ReplaceCallback() {\r
+    public String foundMatch(ArrayList<String> s) {\r
+      if (s.get(1) == null || s.get(1).length() == 0) {\r
+        s.set(1, "*");\r
+      }\r
+      if (s.get(3) == null || s.get(3).length() == 0) {\r
+        s.set(3, "");\r
+      }\r
+      return s.get(1) + "[@" + s.get(2) + s.get(3) + "]";\r
+    }\r
+  };\r
+  \r
   private static ReplaceCallback rc_nth_child = new ReplaceCallback() {\r
     public String foundMatch(ArrayList<String> s) {\r
-      if (s.get(1).length() == 0) {\r
+      if (s.get(1) == null || s.get(1).length() == 0) {\r
         s.set(1, "0");\r
       }\r
       if ("n".equals(s.get(2))) {\r
@@ -82,7 +94,8 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl {
   };\r
 \r
   private static Object[] regs = new Object[]{\r
-    "\\[([^\\]~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]", "[@$1$2]",\r
+    // tag[attrib=value]\r
+    "([a-zA-Z0-9_\\-\\*\\[\\]])?\\[([^\\]@~\\$\\*\\^\\|\\!]+)(=[^\\]]+)?\\]", rc_Attr,\r
     // multiple queries\r
     "\\s*,\\s*", "|",\r
     // , + ~ >\r
@@ -98,9 +111,7 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl {
     "([\\>\\+\\|\\~\\,\\s])([a-zA-Z\\*]+)", "$1//$2",\r
     "\\s+//", "//",\r
     // :first-child\r
-    "([a-zA-Z0-9_\\-\\*]+):first-child", "*[1]/self::$1",\r
-    // :first\r
-    "([a-zA-Z0-9_\\-\\*]+):first", "*[1]/self::$1",\r
+    "([a-zA-Z0-9_\\-\\*]+):first-child", "$1[not(preceding-sibling::*)]",\r
     // :last-child\r
     "([a-zA-Z0-9_\\-\\*]+):last-child", "$1[not(following-sibling::*)]",\r
     // :only-child\r
@@ -127,7 +138,10 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl {
     "#([a-zA-Z0-9_\\-]+)", "[@id='$1']",\r
     "\\.([a-zA-Z0-9_\\-]+)", "[contains(concat(' ',normalize-space(@class),' '),' $1 ')]",\r
     // normalize multiple filters\r
-    "\\]\\[([^\\]]+)", " and ($1)"};\r
+    "\\]\\[([^\\]]+)", " and ($1)",\r
+    // tag:attrib\r
+    "([a-zA-Z0-9_\\-\\*]+):([a-zA-Z0-9_\\-]+)", "$1[@$2='$2']"\r
+    };\r
   \r
   public static SelectorEngineCssToXPath getInstance() {\r
     if (instance == null) {\r
@@ -173,12 +187,12 @@ public class SelectorEngineCssToXPath extends SelectorEngineImpl {
     for (int i = 0; i < regs.length;) {\r
       ret = replacer.replaceAll(ret, regs[i++].toString(), regs[i++]);\r
     }\r
-    return "//" + ret;\r
+    return ".//" + ret;\r
   }\r
   \r
   public NodeList<Element> select(String sel, Node ctx) {\r
     JSArray elm = JSArray.create();\r
-    if (!sel.startsWith("//") && !sel.startsWith("./") && !sel.startsWith("/")) {\r
+    if (!sel.startsWith("./") && !sel.startsWith("/")) {\r
       sel = css2Xpath(sel);\r
     }\r
     SelectorEngine.xpathEvaluate(sel, ctx, elm);\r
index 0b07abc5d29dee200e36a03ff095ea091330df2a..afbaaa14d8db541965aa8eb285422c823817e10a 100644 (file)
@@ -15,6 +15,7 @@
  */\r
 package com.google.gwt.query.client.impl;\r
 \r
+import com.google.gwt.core.client.JsArray;\r
 import com.google.gwt.dom.client.Document;\r
 import com.google.gwt.dom.client.Element;\r
 import com.google.gwt.dom.client.Node;\r
@@ -369,7 +370,7 @@ public class SelectorEngineJS extends SelectorEngineImpl {
       elm.pushAll(prevElem);\r
     }\r
 \r
-    return elm;\r
+    return unique(elm.<JsArray<Element>>cast()).cast();\r
   }\r
 \r
   protected String getAttr(Element current, String name) {\r
index 45b52f2bbde5d388c4f09a3c426150a243ff47ba..578ce977d2e5f4276befd4d186c76c19788b1fc5 100644 (file)
@@ -18,6 +18,7 @@ package com.google.gwt.query.client.impl;
 import static com.google.gwt.query.client.SelectorEngine.eq;\r
 import static com.google.gwt.query.client.SelectorEngine.truth;\r
 \r
+import com.google.gwt.core.client.JsArray;\r
 import com.google.gwt.dom.client.Element;\r
 import com.google.gwt.dom.client.Node;\r
 import com.google.gwt.dom.client.NodeList;\r
@@ -59,8 +60,6 @@ public class SelectorEngineXPath extends SelectorEngineImpl {
 \r
   private Regexp combinator;\r
   \r
-  private SelectorEngineImpl jsEngine = null;\r
-\r
   public SelectorEngineXPath() {\r
   }\r
 \r
@@ -140,16 +139,9 @@ public class SelectorEngineXPath extends SelectorEngineImpl {
           }\r
         }\r
       }\r
-      try {\r
-        SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm).cast();  \r
-      } catch (Exception e) {\r
-        if (jsEngine == null) {\r
-          jsEngine = new SelectorEngineSizzle();\r
-        }\r
-        return jsEngine.select(sel, ctx).cast();\r
-      }\r
+      SelectorEngine.xpathEvaluate(xPathExpression, ctx, elm);\r
     }\r
-    return elm;\r
+    return unique(elm.<JsArray<Element>>cast()).cast();\r
   }\r
 \r
   private void init() {\r
index 7bbc438e8002247f0e4a43c407aed2e726342c8d..4b730e7c22b9a0a5a784a4a03dd88062ee8fc076 100644 (file)
@@ -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("<table><tr><td><p myCustomAttr='whatever'><input type='radio' name='wantedName' value='v1'>1</input></p><input type='radio' name='n' value='v2' checked='checked'>2</input></td><td><button myCustomAttr='val'>Click</button></tr><td></table>");
-    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("<spam><p>s</p></spam>");
+    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(
             "<input type='radio' name='n' value='v1'>1</input>"
@@ -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);
   }
index 43d15416e69b82075662564c987a6881bcc0730f..1f4f3e2783a98280a0fcb7a5208157b0c2b70c7f 100644 (file)
@@ -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]"));    
+    
   }
 
 
index 4f60579796326deebb855c495a0d11a3d4c4edf6..1ace9d523bfa882a7a1f057026440c638be32fc4 100644 (file)
@@ -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() {