diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2012, Nebuta Lab
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Nebuta Lab nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Text/XML/Scraping.hs b/Text/XML/Scraping.hs
new file mode 100644
--- /dev/null
+++ b/Text/XML/Scraping.hs
@@ -0,0 +1,141 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- |Scraping (innerHTML/innerText) and modification (node removal) functions.
+module Text.XML.Scraping where
+
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import Text.XML as X
+import Text.XML.Cursor
+import Data.String
+import qualified Text.HTML.DOM as H
+import qualified Data.Map as M
+import Data.List
+import Data.Maybe
+import System.Environment (getArgs)
+import Text.Blaze.Html as Bl
+import Text.Blaze.Html.Renderer.Text
+import Data.Text.Lazy  (fromStrict,toStrict, unpack)
+
+import Text.XML.Selector
+import Text.XML.Selector.Types
+
+-- * InnerHTML / InnerText
+
+-- |Get ''innerHTML'' from a list of cursors.
+innerHtml :: [Cursor] -> TL.Text
+innerHtml cs = renderNodes $ map node $ concatMap child cs
+
+-- |Get ''innerText'' from a list of cursors.
+innerText :: [Cursor] -> T.Text
+innerText cs = T.concat $ map (innerTextN . node) cs
+-- |''toHTML'' of a list of nodes.
+renderNodes :: [Node] -> TL.Text
+renderNodes ns = TL.concat $ map (renderHtml . Bl.toHtml) ns
+
+-- |''toHTML'' of a list of cursors.
+toHtml :: [Cursor] -> TL.Text
+toHtml cs = renderNodes $ map node cs
+
+-- |''innerText'' of a single node.
+innerTextN :: Node -> T.Text
+innerTextN (NodeElement (Element _ _ cs)) = T.concat $ map innerTextN cs
+innerTextN (NodeContent txt) = txt
+innerTextN _ = ""
+
+-- * Attirbutes
+-- |Tag name of element node. Return Nothing if the node is not an element.
+ename :: Node -> Maybe T.Text
+ename (NodeElement (Element n _ _)) = Just $ nameLocalName n
+ename _ = Nothing
+
+-- |Return an element id. If node is not an element or does not have an id, return Nothing.
+eid :: Node -> Maybe T.Text
+eid (NodeElement (Element _ as _)) = M.lookup "id" as
+eid _ = Nothing
+
+-- |Return element classes. If node is not an element or does not have a class, return an empty list.
+eclass :: Node -> [T.Text]
+eclass (NodeElement (Element _ as _)) = maybe [] T.words $ M.lookup "class" as
+eclass _ = []
+
+-- | Search a meta with a specified name under a cursor, and get a ''content'' field. 
+getMeta :: T.Text -> Cursor -> [T.Text] 
+getMeta n cursor = concat $ cursor $// element "meta" &| attributeIs "name" n &.// attribute "content"
+
+
+-- * Removing Nodes
+-- |Remove descendant nodes that satisfie predicate (''Destructive'').
+remove :: (Node->Bool)->Node->Node
+remove f (NodeElement (Element a b cs)) = NodeElement (Element a b (map (remove f) (filter (not . f) cs)))
+remove _ n = n
+
+-- |Similar to 'remove', but with a depth.
+removeDepth :: (Node->Bool)->Int->Node->Node
+removeDepth _ (-1) n = n
+removeDepth f d (NodeElement (Element a b cs)) = NodeElement (Element a b (map (removeDepth f (d-1)) (filter (not . f) cs)))
+removeDepth _ _ n = n
+
+-- |Remove elements with specified tags.
+removeTags :: [T.Text] -> [Node] -> [Node]
+removeTags ts ns = map (remove (\n -> ename n `elem` map Just ts)) ns
+
+-- |Remove descendant nodes that match a query string.
+removeQuery :: String -> [Node] -> [Node]
+removeQuery q ns = map (remove (queryMatchNode q)) ns
+
+-- |Remove descendant nodes that match any of query strings.
+removeQueries :: [String] -> [Node] -> [Node]
+removeQueries qs ns = map (remove f) ns
+  where
+    f :: Node -> Bool
+    f n = any (flip queryMatchNode n) qs
+
+-- |See if the node contains any descendant (and self) node that satisfies predicate.
+-- To return false, this function needs to traverse all descendant elements....
+nodeHaving :: (Node->Bool)->Node->Bool
+nodeHaving f n@(NodeElement (Element _ _ cs)) = f n || any (nodeHaving f) cs
+nodeHaving _ _ = False
+
+
+-- |Remove descendant nodes that match the condition (similar to 'remove')
+rmElem :: String -> String -> [String] -> [Node] -> [Node]
+rmElem tag id kl ns = map (remove f) ns
+  where
+    f :: Node -> Bool
+    f (NodeElement e) = selectorMatch (JQSelector Descendant (g tag) (g id) kl []) e
+    f _ = False
+    g :: String -> Maybe String
+    g "" = Nothing
+    g s = Just s
+
+
+--
+-- Conversion to trees
+--
+{-
+toTree :: Node -> Tr.Tree String
+toTree (TextNode t) = Tr.Node ("\""++T.unpack t++"\"") []
+toTree (Comment t) = Tr.Node ("<-- "++T.unpack t++" -->") []
+toTree (Element t as c) = Tr.Node str (map toTree c)
+	where
+		str = T.unpack t ++ g as
+		g as | null as = ""
+					| otherwise = ": [" ++ intercalate "," (map f as) ++ "]"
+		f (k,v) = T.unpack k ++ "=\"" ++ T.unpack v ++ "\""
+
+
+showTree :: [Node] -> IO ()
+showTree ns = do
+	mapM_ (putStr . Tr.drawTree . toTree) ns
+-}
+--
+-- Helper functions for XmlHtml data
+--
+{-
+(!!!) :: Node -> Int -> Node
+(Element _ _ c) !!! i = c !! i
+_ !!! _ = error "No child elements"
+-}
+
+
diff --git a/Text/XML/Selector.hs b/Text/XML/Selector.hs
new file mode 100644
--- /dev/null
+++ b/Text/XML/Selector.hs
@@ -0,0 +1,219 @@
+{-# LANGUAGE OverloadedStrings, DoAndIfThenElse, TemplateHaskell, QuasiQuotes #-}
+
+--  CSS selector for Text.XML (xml-conduit) library.
+--
+--
+-- Examples
+-- doc <- H.readFile "input.html"
+-- let c = fromDocument c
+-- c $| query
+-- c $| query "meta[name='dc.Creator']" >=> attribute "content"
+
+-- |This module has query functions for traversing DOM. 'queryT', a quasiquote version, is also available in "Text.XML.Selector.TH" module.
+module Text.XML.Selector (
+  query,
+  query1,
+  searchTree,
+  showJQ,
+  byId,
+  byClass,
+  selectorMatch,
+  next,
+  maybeText,
+  headm,
+  queryMatchNode
+  )
+where
+
+-- import Import
+-- import qualified Data.Tree as Tr
+import Data.List
+import qualified Data.Text as T
+import Text.XML.Cursor
+import Text.XML as X -- hiding (Name)
+-- import Data.Either.Utils
+import qualified Data.Map as M
+import Data.Maybe
+-- import Language.Haskell.TH (runQ)
+import Text.XML.Selector.Parser
+import Text.XML.Selector.Types
+import Debug.Trace
+
+
+-- | Show a parsed selector.
+-- (parseJQ . showJQ) == id
+showJQ :: [JQSelector] -> String
+showJQ ss = foldl f "" ss
+  where
+    f str sel = str ++ g (relPrev sel) ++ 
+      maybe "" id (jqTagName sel) ++
+      maybe "" (("#"++)) (jqTagId sel) ++ 
+      concat (map (("."++)) (jqTagClass sel)) ++
+      if null (jqTagAttr sel) then "" else (concatMap h (jqTagAttr sel))
+    g Descendant = " "
+    g Child = " > "
+    g Next = " + "
+    g Sibling = " ~ "
+    h (TagAttr k Nothing _) = "["++k++"]"
+    h (TagAttr k (Just v) r) = "["++k ++ relToStr r ++ "\"" ++ v ++ "\"]"
+--    h _ = error "Invalid TagAttr"
+
+
+-- Some elementary search
+
+-- | Axis for choosing elements by an id
+byId :: String -> Axis
+byId s = checkElement (elemHasId (Just s))
+
+-- byIdT :: String -> Axis
+byIdT s = [e| checkElement (elemHasId (Just s)) |]
+
+-- | Axis for choosing elements by a class
+byClass :: String -> Axis
+byClass s = checkElement (elemHasClass [s])
+
+-- Some traversing
+
+-- |Gets the next sibling. Note that this is not a Axis.
+next :: Cursor -> Maybe Cursor
+next c = headm (c $| followingSibling)
+
+
+-- Auxiliary functions
+headm :: [a] -> Maybe a
+headm [] = Nothing
+headm (x:_) = Just x
+
+take1' :: [a] -> [a]
+take1' xs = if null xs then [] else take 1 xs
+
+maybeText :: T.Text -> Maybe T.Text
+maybeText "" = Nothing
+maybeText t = Just t
+
+--
+-- Traversing by jQuery string
+--
+
+
+-- | Get 'Axis' from jQuery selector string.
+query :: String -> Axis
+query keystr = case parseJQ keystr of
+                 [] -> error "query: Invalid selector"
+                 sels -> searchTree sels
+
+
+-- | Return Just (the first element of query results). If no element matches, it returns Nothing.
+query1 :: String -> Cursor -> Maybe Cursor
+query1 s n | null res = Nothing
+	| otherwise = Just (head res)
+	where res = query s n
+
+{-
+-- | Old version: search direction should be child -> parent to avoid duplicates for nested elements with same tag.
+searchTreeOld :: [JQSelector] -> Axis
+searchTreeOld [] c = [c]
+searchTreeOld (x@(JQSelector Descendant _ _ _ _):xs) c = c $// checkElement (selectorMatch x)  >=> searchTree xs
+searchTreeOld (x@(JQSelector Child _ _ _ _):xs) c = c $/ checkElement (selectorMatch x) >=> searchTree xs
+searchTreeOld (x@(JQSelector Next _ _ _ _):xs) c =
+  case c $| followingSibling >=> anyElement of
+    [] -> []
+    cs -> (head cs) $| checkElement (selectorMatch x) >=> searchTree xs
+searchTreeOld ((JQSelector Sibling _ _ _ _):xs) c =  c $| followingSibling >=> searchTree xs
+-}
+
+searchTree :: [JQSelector] -> Axis
+searchTree xs = search (reverse xs)
+  where
+    search [] c = [c]
+    search (x@(JQSelector rel _ _ _ _):xs) c = c $// checkElement (selectorMatch x) >=> check (traceAncestors rel xs)
+
+
+traceAncestors :: RelPrev -> [JQSelector] -> Axis
+traceAncestors _ [] c = [c]
+traceAncestors Child (x:xs) c
+  | isJust p = if matchCursor x (fromJust p) then traceAncestors (relPrev x) xs (fromJust p) else []
+  | otherwise = []
+    where
+      p :: Maybe Cursor
+      p = headm (parent c)
+traceAncestors Descendant (x:xs) c
+  = case filter (matchCursor x) (ancestor c) of
+      [] -> []
+      as -> concatMap (traceAncestors (relPrev x) xs) as
+traceAncestors Next (x:xs) c
+  | isJust p = if matchCursor x (fromJust p) then traceAncestors (relPrev x) xs (fromJust p) else []
+  | otherwise = []
+    where
+      p :: Maybe Cursor
+      p = headm (precedingSibling c)
+traceAncestors Sibling (x:xs) c
+  = case filter (matchCursor x) (precedingSibling c) of
+      [] -> []
+      as -> concatMap (traceAncestors (relPrev x) xs) as
+
+
+-- |Return if an element matches a selector
+selectorMatch :: JQSelector -> Element -> Bool
+selectorMatch (JQSelector _ name id klass attr) e
+  = elemIsTag name e && elemHasId id e && elemHasClass klass e && all (flip elemHasAttr e) attr
+
+matchNode :: JQSelector -> Node -> Bool
+matchNode sel (NodeElement elem) = selectorMatch sel elem
+matchNode _ _ = False
+
+matchCursor :: JQSelector -> Cursor -> Bool
+matchCursor sel cursor = matchNode sel (node cursor)
+
+-- |Return if a node matches a selector given by string
+-- |Only first token is used (i.e. no hierarchy is enabled.)
+queryMatchNode :: String -> Node -> Bool
+queryMatchNode s (NodeElement e)
+    = case qq of
+        Just q -> selectorMatch q e
+        Nothing -> False
+  where qq = headm $ parseJQ s
+queryMatchNode _ _ = False
+
+
+-- return False when tag is specified in selector (1st arg) but not the one in the element (2nd arg)
+elemIsTag :: Maybe String -> Element -> Bool
+elemIsTag Nothing _ = True
+elemIsTag (Just tag) (Element n _ _) = nameLocalName n == T.pack tag
+
+elemHasId :: Maybe String -> Element -> Bool
+elemHasId Nothing _ = True
+elemHasId (Just id) (Element _ as _) = M.lookup "id" as == Just (T.pack id)
+
+elemHasClass :: [String] -> Element -> Bool
+elemHasClass [] _ = True
+elemHasClass ks (Element _ as _) = all (`elem` kl) $ map T.pack ks
+  where
+      kl = maybe [] T.words (M.lookup "class" as)
+
+
+-- This is different from the above three funcs: by default return False
+elemHasAttr :: TagAttr -> Element -> Bool
+elemHasAttr attr (Element _ as _) = relFunc (attrRel attr) (g as) (Just (fromMaybe "" (attrVal attr)))
+  where
+    relFunc :: AttrRel -> Maybe String -> Maybe String -> Bool
+    relFunc Equal (Just a) (Just b) = a == b
+    relFunc Exists a _ = isJust a   -- '[checked]'
+    relFunc Contains (Just a) (Just b) = b `isInfixOf` a
+    relFunc Begin (Just a) (Just b) = b `isPrefixOf` a
+    relFunc End (Just a) (Just b) = b `isSuffixOf` a
+    relFunc NotEqual (Just a) (Just b) = a /= b
+    relFunc ContainsWord (Just a) (Just b) = all (`isInfixOf` a) (words b)
+    relFunc _ _ _ = False
+--    relFunc r a b = error ("Attribute query invalid pattern: " ++ show attr ++ " : " ++ show r ++ show a ++ show b)
+--    nameToStr :: M.Map Name T.Text -> M.Map String T.Text
+--    nameToStr m = trace (show m) m
+    toName s = Name (T.pack s) Nothing Nothing
+    g :: M.Map Name T.Text -> Maybe String
+    g as = fmap T.unpack (M.lookup (toName $ attrName attr) as)
+    
+
+-- elemClass :: Element -> [T.Text]
+-- elemClass (Element _ a _) = concat $ maybeToList $ fmap T.words $ (M.lookup "class" a)
+
+
diff --git a/Text/XML/Selector/Parser.hs b/Text/XML/Selector/Parser.hs
new file mode 100644
--- /dev/null
+++ b/Text/XML/Selector/Parser.hs
@@ -0,0 +1,113 @@
+--
+-- Parsers for CSS query strings
+--
+{-# LANGUAGE DoAndIfThenElse #-}
+
+module Text.XML.Selector.Parser (parseJQ) where
+import Text.Parsec
+-- import Data.Either.Utils
+import Text.XML.Selector.Types
+
+import Data.Maybe
+import qualified Data.Map as M
+
+type Parser a = Parsec String () a
+
+-- | Parse a jQuery selector string and return a list of 'JQSelector'.
+parseJQ :: String -> [JQSelector]
+parseJQ s = either (const []) id (parse parseKey "" (s++" ")) -- (++" ") is super ad hoc!!
+
+-- test_parseQuery s = forceEither $ parse parseKey "" (s++" ") 
+
+data JQSelectorToken = JQSelectorToken {
+	rel :: RelPrev,
+	tagNameIdClassAttr :: [NameIdClassAttr]
+} deriving (Eq,Show)
+
+transformSelector :: JQSelectorToken -> JQSelector
+transformSelector (JQSelectorToken rel name) = JQSelector rel (t1 t) (t2 t) (t3 t) (t4 t)
+  where
+    t = f name (Nothing,Nothing,[],[])
+    f [] r = r
+    f ((TagName s):xs) r = f xs (Just s,t2 r,t3 r,t4 r)
+    f ((Id s):xs) r = f xs (t1 r,Just s,t3 r,t4 r)
+    f ((Class s):xs) r = f xs (t1 r,t2 r,s:t3 r,t4 r)
+    f ((Attr k op v):xs) r = f xs (t1 r,t2 r,t3 r,(g k op v):(t4 r))
+    t1 (a,_,_,_) = a
+    t2 (_,a,_,_) = a
+    t3 (_,_,a,_) = a
+    t4 (_,_,_,a) = a
+    g k op v = TagAttr k v (fromMaybe Exists (op >>= (flip M.lookup attrOpList)))
+    
+attrOpList :: M.Map String AttrRel
+attrOpList = M.fromList [("=",Equal),("|=",Contains),("!=",NotEqual),("^=",Begin),("$=",End),("*=",ContainsWord)]
+
+parseKey :: Parser [JQSelector]
+parseKey = many1 selector
+
+selector :: Parser JQSelector
+selector = do
+  skipMany myspaces
+  sep <- optionMaybe (choice (map char ">+~"))
+  let t = case sep of
+            Just '>' -> Child
+            Just '+' -> Next
+            Just '~' -> Sibling
+            Nothing -> Descendant
+            _ -> error "Incorrect option."
+  skipMany myspaces
+  tok <- many1 $ choice [try selId, try selClass, try selTag, try selAttr]
+  skipMany myspaces
+  return $ transformSelector (JQSelectorToken t tok)
+
+data NameIdClassAttr = TagName String | Id String | Class String | Attr String (Maybe String) (Maybe String) deriving (Eq,Show,Ord)
+
+selTag :: Parser NameIdClassAttr
+selTag = do
+	s <- many1 cssChar
+	return $ TagName s
+
+selId :: Parser NameIdClassAttr
+selId = do
+  char '#'
+  s <- many1 cssChar
+  return $ Id s
+
+selClass :: Parser NameIdClassAttr
+selClass = do
+	char '.'
+	s <- many1 cssChar
+	return $ Class s
+
+selAttr :: Parser NameIdClassAttr
+selAttr = do
+  char '['
+  k <- many1 cssChar
+  op <- optionMaybe attrOp
+  q <- optionMaybe (oneOf "\"'")
+  v <- optionMaybe $ many1 (noneOf (maybe "]" (:[]) q))
+  if isJust q then do
+    char (fromJust q)
+  else do
+    return ' '
+  char ']'
+  return (Attr k op v)
+
+-- stopDelim = (lookAhead (choice (map char ".#>+~ \t")))
+
+--
+-- Tokens
+--
+-- myspaces :: Stream s m Char => ParsecT s u m Char
+myspaces = choice (map char " \t\r\n")
+
+-- attrOp :: Stream s m Char => ParsecT s u m String
+attrOp = choice $ map string ["=","|=","!=","*=","$=","^="]
+
+-- cssChar :: Stream s m Char => ParsecT s u m Char
+cssChar = oneOf "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
+
+
+
+
+
diff --git a/Text/XML/Selector/TH.hs b/Text/XML/Selector/TH.hs
new file mode 100644
--- /dev/null
+++ b/Text/XML/Selector/TH.hs
@@ -0,0 +1,46 @@
+{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
+
+module Text.XML.Selector.TH (jq,queryT) where 
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+import Language.Haskell.TH.Lift
+import Text.Parsec
+import Text.XML.Selector
+import Text.XML.Cursor
+
+import Text.Parsec
+import Text.XML.Selector.Types
+import Text.XML.Selector.Parser
+
+import Data.Maybe
+import qualified Data.Map as M
+
+type Parser a = Parsec String () a
+
+$(deriveLift ''JQSelector)
+$(deriveLift ''TagAttr)
+$(deriveLift ''RelPrev)
+$(deriveLift ''AttrRel)
+
+-- instance Lift JQSelector where
+--  lift (JQSelector a b c d e) = [| JQSelector a b c d e |]
+
+jqueryExpr :: String -> Q Exp
+jqueryExpr str = do
+  case parseJQ str of
+                 [] -> error "query: Invalid selector"
+                 sels -> [| sels |]
+
+-- | QuasiQuoter for CSS selector
+jq :: QuasiQuoter
+jq = QuasiQuoter jqueryExpr undefined undefined undefined
+
+
+-- |Get 'Axis' from jQuery selector QQ.
+--
+-- >html = innerHtml $ cursor $| queryT [jq| ul.foo > li#bar |]
+queryT :: [JQSelector] -> Axis
+queryT sels = searchTree sels
+
+
+
diff --git a/Text/XML/Selector/Test.hs b/Text/XML/Selector/Test.hs
new file mode 100644
--- /dev/null
+++ b/Text/XML/Selector/Test.hs
@@ -0,0 +1,57 @@
+--
+-- Testing
+--
+
+module Text.XML.Selector.Test (prop_parseJQ) where
+
+import Text.XML.Selector (showJQ)
+import Text.XML.Selector.Types
+import Text.XML.Selector.Parser
+import Test.QuickCheck
+import Control.Monad
+import Data.Maybe
+
+-- |QuickCheck for a parser.
+prop_parseJQ :: [JQSelector] -> Bool
+prop_parseJQ ss = (parseJQ . showJQ) ss == ss
+
+
+instance Arbitrary JQSelector where
+  arbitrary = do
+    rel <- arbitrary
+    nm <- arbCssId
+    a <- choose (0,1)
+    let name = [Nothing, Just nm] !! a
+    ids <- arbCssId
+    c <- choose (0,1)
+    let id = [Nothing, Just ids] !! c
+    kl <- arbCssId
+    b <- choose (0,10)
+    klass <- replicateM b arbCssId
+    attr <- case (name, id, klass) of
+              (Nothing, Nothing, []) -> do
+                n <- choose (1,10)
+                replicateM n (arbitrary :: Gen TagAttr)
+              _ -> arbitrary
+    return (JQSelector rel name id klass attr)
+
+instance Arbitrary TagAttr where
+  arbitrary = do
+    name <- arbCssId
+    rel <- arbitrary
+    s <- arbCssId
+    let v = Just s
+    let val = if rel == Exists then Nothing else v
+    return (TagAttr name val rel)
+
+instance Arbitrary RelPrev where
+  arbitrary = elements (enumFrom (toEnum 0))
+
+instance Arbitrary AttrRel where
+  arbitrary = elements (enumFrom (toEnum 0))
+
+
+arbCssId :: Gen String
+arbCssId = do
+  n <- choose (1,10)
+  replicateM n (elements "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
diff --git a/Text/XML/Selector/Types.hs b/Text/XML/Selector/Types.hs
new file mode 100644
--- /dev/null
+++ b/Text/XML/Selector/Types.hs
@@ -0,0 +1,32 @@
+module Text.XML.Selector.Types where 
+
+import Data.List (sort)
+import qualified Data.Map as M (lookup,fromList)
+import Data.Maybe (fromMaybe)
+
+-- |JQSelector represents one token of jquery selector. One JQSelector corresponds to \"div#content\", \"a[href='/index.html']\", etc. You can get a list of JQSelector by 'parseJQ', and show them by 'showJQ'
+-- As long as you use 'query', you don't need to handle this type directly.
+data JQSelector = JQSelector {
+	relPrev :: RelPrev,
+  jqTagName :: Maybe String,
+	jqTagId :: Maybe String,
+	jqTagClass :: [String],
+  jqTagAttr :: [TagAttr]
+} deriving (Show,Read,Ord)
+
+instance Eq JQSelector where
+  (JQSelector r1 n1 i1 c1 a1) == (JQSelector r2 n2 i2 c2 a2) = r1 == r2 && n1 == n2 && i1 == i2 && (sort c1 == sort c2 && sort a1 == sort a2)
+
+data TagAttr = TagAttr {
+  attrName :: String,
+  attrVal :: Maybe String,
+  attrRel :: AttrRel
+} deriving (Eq,Show,Read,Ord)
+
+data AttrRel = Equal | Begin | End | Contains | NotEqual | ContainsWord | Exists deriving (Show,Eq,Ord,Enum,Read)
+relToStr :: AttrRel -> String
+relToStr r = fromMaybe "N/A" $ M.lookup r (M.fromList [(Equal,"="),(Begin,"^="),(End,"$="),(Contains,"|="),(NotEqual,"!="),(ContainsWord,"*=")])
+
+-- |Relationship to the preceding selector.
+data RelPrev = Descendant | Child | Next | Sibling deriving (Eq,Show,Enum,Read,Ord)
+
diff --git a/dom-selector.cabal b/dom-selector.cabal
new file mode 100644
--- /dev/null
+++ b/dom-selector.cabal
@@ -0,0 +1,54 @@
+-- Initial dom-selector.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+-- The name of the package.
+name:                dom-selector
+version:             0.1.0.0
+synopsis:            DOM traversal by CSS selectors for xml-conduit package
+description:
+  CSS selector support for xml-conduit/html-conduit. This package supports compile-time checking of CSS selectors using quasiquotes.
+  .
+  * Quick start
+  .
+  > -- The following pragmas should be put first (Haddock does not accept a pragma notation.)
+  > -- LANGUAGE OverloadedStrings, QuasiQuotes
+  > module Main (main) where
+  >
+  > import Text.XML.Cursor
+  > import qualified Text.HTML.DOM as H (readFile)
+  > import qualified Data.Text.Lazy.IO as TI (putStrLn)
+  > import Text.XML.Scraping (innerHtml)
+  > import Text.XML.Selector.TH 
+  >
+  > main :: IO ()
+  > main = do
+  >   c <- fmap fromDocument $ H.readFile "input.html"
+  >   let cs = queryT [jq| ul#foo > li.bar |] c
+  >   TI.putStrLn $ innerHtml cs
+  .
+  You can use some elementary CSS selectors for traversing a DOM tree.
+  .
+  * Other examples
+  .
+  <https://github.com/nebuta/dom-selector/tree/master/examples>
+
+homepage:            https://github.com/nebuta/
+license:             BSD3
+license-file:        LICENSE
+author:              Nebuta Lab
+maintainer:          nebuta.office@gmail.com
+copyright:           Copyright 2012 by Nebuta Lab           
+category:            Web
+stability:           alpha
+build-type:          Simple
+cabal-version:       >=1.8
+
+source-repository head
+  type:     git
+  location: https://github.com/nebuta/dom-selector
+
+library
+  exposed-modules:     Text.XML.Scraping, Text.XML.Selector, Text.XML.Selector.Parser, Text.XML.Selector.Test, Text.XML.Selector.TH, Text.XML.Selector.Types
+  other-modules:       
+  build-depends:       base >=4.0 && <5, text ==0.11.*, xml-conduit, html-conduit >=0.1, containers >=0.4, blaze-html >=0.5,  parsec >=3.1, QuickCheck >=2.4, template-haskell >=2.5, th-lift >=0.5
+  
