hexpat 0.9 → 0.10
raw patch · 7 files changed
+245/−32 lines, 7 filesdep ~textPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: text
API changes (from Hackage documentation)
+ Text.XML.Expat.Annotated: ASCII :: Encoding
+ Text.XML.Expat.Annotated: CharacterData :: text -> SAXEvent tag text
+ Text.XML.Expat.Annotated: Element :: !tag -> ![(tag, text)] -> [Node tag text a] -> a -> Node tag text a
+ Text.XML.Expat.Annotated: EndElement :: tag -> SAXEvent tag text
+ Text.XML.Expat.Annotated: FailDocument :: XMLParseError -> SAXEvent tag text
+ Text.XML.Expat.Annotated: ISO88591 :: Encoding
+ Text.XML.Expat.Annotated: NName :: Maybe text -> !text -> NName text
+ Text.XML.Expat.Annotated: QName :: Maybe text -> !text -> QName text
+ Text.XML.Expat.Annotated: StartElement :: tag -> [(tag, text)] -> SAXEvent tag text
+ Text.XML.Expat.Annotated: Text :: !text -> Node tag text a
+ Text.XML.Expat.Annotated: UTF16 :: Encoding
+ Text.XML.Expat.Annotated: UTF8 :: Encoding
+ Text.XML.Expat.Annotated: XMLParseError :: String -> XMLParseLocation -> XMLParseError
+ Text.XML.Expat.Annotated: XMLParseException :: XMLParseError -> XMLParseException
+ Text.XML.Expat.Annotated: XMLParseLocation :: Int64 -> Int64 -> Int64 -> Int64 -> XMLParseLocation
+ Text.XML.Expat.Annotated: class (Monoid s, Eq s) => GenericXMLString s
+ Text.XML.Expat.Annotated: data Encoding
+ Text.XML.Expat.Annotated: data NName text
+ Text.XML.Expat.Annotated: data Node tag text a
+ Text.XML.Expat.Annotated: data QName text
+ Text.XML.Expat.Annotated: data SAXEvent tag text
+ Text.XML.Expat.Annotated: data XMLParseError
+ Text.XML.Expat.Annotated: data XMLParseException
+ Text.XML.Expat.Annotated: data XMLParseLocation
+ Text.XML.Expat.Annotated: eAnn :: Node tag text a -> a
+ Text.XML.Expat.Annotated: eAttrs :: Node tag text a -> ![(tag, text)]
+ Text.XML.Expat.Annotated: eChildren :: Node tag text a -> [Node tag text a]
+ Text.XML.Expat.Annotated: eName :: Node tag text a -> !tag
+ Text.XML.Expat.Annotated: gxBreakOn :: (GenericXMLString s) => Char -> s -> (s, s)
+ Text.XML.Expat.Annotated: gxFromCStringLen :: (GenericXMLString s) => CStringLen -> IO s
+ Text.XML.Expat.Annotated: gxFromChar :: (GenericXMLString s) => Char -> s
+ Text.XML.Expat.Annotated: gxFromString :: (GenericXMLString s) => String -> s
+ Text.XML.Expat.Annotated: gxHead :: (GenericXMLString s) => s -> Char
+ Text.XML.Expat.Annotated: gxNullString :: (GenericXMLString s) => s -> Bool
+ Text.XML.Expat.Annotated: gxTail :: (GenericXMLString s) => s -> s
+ Text.XML.Expat.Annotated: gxToByteString :: (GenericXMLString s) => s -> ByteString
+ Text.XML.Expat.Annotated: gxToString :: (GenericXMLString s) => s -> String
+ Text.XML.Expat.Annotated: instance (Eq tag, Eq text, Eq a) => Eq (Node tag text a)
+ Text.XML.Expat.Annotated: instance (Show tag, Show text, Show a) => Show (Node tag text a)
+ Text.XML.Expat.Annotated: instance Functor (Node tag text)
+ Text.XML.Expat.Annotated: mkAnNName :: text -> NName text
+ Text.XML.Expat.Annotated: mkNName :: text -> text -> NName text
+ Text.XML.Expat.Annotated: nnLocalPart :: NName text -> !text
+ Text.XML.Expat.Annotated: nnNamespace :: NName text -> Maybe text
+ Text.XML.Expat.Annotated: parseSAX :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> [SAXEvent tag text]
+ Text.XML.Expat.Annotated: parseSAXLocations :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> [(SAXEvent tag text, XMLParseLocation)]
+ Text.XML.Expat.Annotated: parseSAXLocationsThrowing :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> [(SAXEvent tag text, XMLParseLocation)]
+ Text.XML.Expat.Annotated: parseSAXThrowing :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> [SAXEvent tag text]
+ Text.XML.Expat.Annotated: parseTree :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> (LNode tag text, Maybe XMLParseError)
+ Text.XML.Expat.Annotated: parseTree' :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> Either XMLParseError (LNode tag text)
+ Text.XML.Expat.Annotated: parseTreeThrowing :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> LNode tag text
+ Text.XML.Expat.Annotated: qnLocalPart :: QName text -> !text
+ Text.XML.Expat.Annotated: qnPrefix :: QName text -> Maybe text
+ Text.XML.Expat.Annotated: saxToTree :: (GenericXMLString tag) => [(SAXEvent tag text, a)] -> (Node tag text a, Maybe XMLParseError)
+ Text.XML.Expat.Annotated: textContent :: (Monoid text) => Node tag text a -> text
+ Text.XML.Expat.Annotated: type Attributes tag text = [(tag, text)]
+ Text.XML.Expat.Annotated: type LNode tag text = Node tag text XMLParseLocation
+ Text.XML.Expat.Annotated: type LNodes tag text = [Node tag text XMLParseLocation]
+ Text.XML.Expat.Annotated: type NAttributes text = Attributes (NName text) text
+ Text.XML.Expat.Annotated: type NLNode text = LNode (NName text) text
+ Text.XML.Expat.Annotated: type NLNodes text = LNodes (NName text) text
+ Text.XML.Expat.Annotated: type NNode text a = Node (NName text) text a
+ Text.XML.Expat.Annotated: type NNodes text a = Nodes (NName text) text a
+ Text.XML.Expat.Annotated: type Nodes tag text a = [Node tag text a]
+ Text.XML.Expat.Annotated: type QAttributes text = Attributes (QName text) text
+ Text.XML.Expat.Annotated: type QLNode text = LNode (QName text) text
+ Text.XML.Expat.Annotated: type QLNodes text = LNodes (QName text) text
+ Text.XML.Expat.Annotated: type QNode text a = Node (QName text) text a
+ Text.XML.Expat.Annotated: type QNodes text a = Nodes (QName text) text a
+ Text.XML.Expat.Annotated: type UAttributes text = Attributes text text
+ Text.XML.Expat.Annotated: type ULNode text = LNode text text
+ Text.XML.Expat.Annotated: type ULNodes text = LNodes text text
+ Text.XML.Expat.Annotated: type UNode text a = Node text text a
+ Text.XML.Expat.Annotated: type UNodes text a = Nodes text text a
+ Text.XML.Expat.Annotated: unannotate :: Node tag text a -> Node tag text
+ Text.XML.Expat.Annotated: xmlByteCount :: XMLParseLocation -> Int64
+ Text.XML.Expat.Annotated: xmlByteIndex :: XMLParseLocation -> Int64
+ Text.XML.Expat.Annotated: xmlColumnNumber :: XMLParseLocation -> Int64
+ Text.XML.Expat.Annotated: xmlLineNumber :: XMLParseLocation -> Int64
+ Text.XML.Expat.Annotated: xmlns :: (GenericXMLString text) => text
+ Text.XML.Expat.Annotated: xmlnsUri :: (GenericXMLString text) => text
+ Text.XML.Expat.IO: getParseLocation :: Parser -> IO XMLParseLocation
+ Text.XML.Expat.Tree: parseSAXLocationsThrowing :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -> ByteString -> [(SAXEvent tag text, XMLParseLocation)]
+ Text.XML.Expat.Tree: textContent :: (Monoid text) => Node tag text -> text
Files
- Text/XML/Expat/Annotated.hs +193/−0
- Text/XML/Expat/Format.hs +1/−3
- Text/XML/Expat/IO.hs +9/−7
- Text/XML/Expat/Qualified.hs +0/−1
- Text/XML/Expat/Tree.hs +35/−14
- hexpat.cabal +3/−3
- test/tests.hs +4/−4
+ Text/XML/Expat/Annotated.hs view
@@ -0,0 +1,193 @@+-- | A variant of /Node/ in which Element nodes have an annotation of any type,+-- and some concrete functions that annotate with the XML parse location.+-- It is assumed you will usually want /Tree/ or /Annotated/, not both, so many+-- of the names conflict.+--+-- Support for qualified and namespaced trees annotated with location information+-- is not complete.+module Text.XML.Expat.Annotated (+ -- * Tree structure+ Node(..),+ Attributes, -- re-export from Tree+ Nodes,+ UNode,+ UNodes,+ UAttributes,+ LNode,+ LNodes,+ ULNode,+ ULNodes,+ textContent,+ unannotate,+ -- * Qualified nodes+ QName(..),+ QNode,+ QNodes,+ QAttributes,+ QLNode,+ QLNodes,+ -- * Namespaced nodes+ NName (..),+ NNode,+ NNodes,+ NAttributes,+ NLNode,+ NLNodes,+ mkNName,+ mkAnNName,+ xmlnsUri,+ xmlns,+ -- * Parse to tree+ parseTree,+ parseTree',+ Encoding(..),+ XMLParseError(..),+ XMLParseLocation(..),+ -- * SAX-style parse+ parseSAX,+ SAXEvent(..),+ saxToTree,+ parseSAXLocations,+ -- * Variants that throw exceptions+ XMLParseException(..),+ parseTreeThrowing,+ parseSAXThrowing,+ parseSAXLocationsThrowing,+ -- * Abstraction of string types+ GenericXMLString(..)+ ) where++import Text.XML.Expat.Tree hiding (Node(..), Nodes, UNode, UNodes, saxToTree,+ parseTree, parseTree', parseTreeThrowing, textContent)+import qualified Text.XML.Expat.Tree as Tree (Node(..))+import Text.XML.Expat.Qualified hiding (QNode, QNodes)+import Text.XML.Expat.Namespaced hiding (NNode, NNodes)++import Control.Monad (mplus)+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L+import Data.Monoid+++-- | Annotated variant of the tree representation of the XML document.+data Node tag text a =+ Element {+ eName :: !tag,+ eAttrs :: ![(tag,text)],+ eChildren :: [Node tag text a],+ eAnn :: a+ } |+ Text !text+ deriving (Eq, Show)++unannotate :: Node tag text a -> Tree.Node tag text+unannotate (Element na at ch _) = (Tree.Element na at (map unannotate ch))+unannotate (Text t) = Tree.Text t++-- | Extract all text content from inside a tag into a single string, including+-- any text contained in children.+textContent :: Monoid text => Node tag text a -> text+textContent (Element _ _ children _) = mconcat $ map textContent children+textContent (Text txt) = txt++-- | Type shortcut for annotated nodes+type Nodes tag text a = [Node tag text a]++-- | Type shortcut for annotated nodes with unqualified tag names where tag and+-- text are the same string type+type UNodes text a = Nodes text text a++-- | Type shortcut for a single annotated node with unqualified tag names where+-- tag and text are the same string type+type UNode text a = Node text text a++-- | Type shortcut for a single annotated node, annotated with parse location+type LNode tag text = Node tag text XMLParseLocation++-- | Type shortcut for annotated nodes with location information.+type LNodes tag text = [Node tag text XMLParseLocation]++-- | Type shortcut for a single node with unqualified tag names where+-- tag and text are the same string type, annotated with parse location+type ULNode text = LNode text text ++-- | Type shortcut for nodes with unqualified tag names where+-- tag and text are the same string type, annotated with parse location+type ULNodes text = LNodes text text++-- | Type shortcut for annotated nodes where qualified names are used for tags+type QNodes text a = Nodes (QName text) text a++-- | Type shortcut for nodes where qualified names are used for tags, annotated with parse location+type QLNodes text = LNodes (QName text) text++-- | Type shortcut for a single annotated node where qualified names are used for tags+type QNode text a = Node (QName text) text a++-- | Type shortcut for a single node where qualified names are used for tags, annotated with parse location+type QLNode text = LNode (QName text) text++-- | Type shortcut for annotated nodes where namespaced names are used for tags+type NNodes text a = Nodes (NName text) text a++-- | Type shortcut for nodes where namespaced names are used for tags, annotated with parse location+type NLNodes text = LNodes (NName text) text++-- | Type shortcut for a single annotated node where namespaced names are used for tags+type NNode text a = Node (NName text) text a++-- | Type shortcut for a single node where namespaced names are used for tags, annotated with parse location+type NLNode text = LNode (NName text) text++instance Functor (Node tag text) where+ f `fmap` Element na at ch an = Element na at (map (f `fmap`) ch) (f an)+ f `fmap` Text t = Text t++-- | A lower level function that lazily converts a SAX stream into a tree structure.+-- Variant that takes annotations for start tags.+saxToTree :: GenericXMLString tag =>+ [(SAXEvent tag text, a)]+ -> (Node tag text a, Maybe XMLParseError)+saxToTree events =+ let (nodes, mError, _) = ptl events+ in (safeHead nodes, mError)+ where+ safeHead (a:_) = a+ safeHead [] = Element (gxFromString "") [] [] (error "saxToTree null annotation")+ ptl ((StartElement name attrs, ann):rem) =+ let (children, err1, rem') = ptl rem+ elt = Element name attrs children ann+ (out, err2, rem'') = ptl rem'+ in (elt:out, err1 `mplus` err2, rem'')+ ptl ((EndElement name, _):rem) = ([], Nothing, rem)+ ptl ((CharacterData txt, _):rem) =+ let (out, err, rem') = ptl rem+ in (Text txt:out, err, rem')+ ptl ((FailDocument err, _):_) = ([], Just err, [])+ ptl [] = ([], Nothing, [])++-- | Lazily parse XML to tree. Note that forcing the XMLParseError return value+-- will force the entire parse. Therefore, to ensure lazy operation, don't+-- check the error status until you have processed the tree.+parseTree :: (GenericXMLString tag, GenericXMLString text) =>+ Maybe Encoding -- ^ Optional encoding override+ -> L.ByteString -- ^ Input text (a lazy ByteString)+ -> (LNode tag text, Maybe XMLParseError)+parseTree mEnc bs = saxToTree $ parseSAXLocations mEnc bs++-- | Lazily parse XML to tree. In the event of an error, throw 'XMLParseException'.+parseTreeThrowing :: (GenericXMLString tag, GenericXMLString text) =>+ Maybe Encoding -- ^ Optional encoding override+ -> L.ByteString -- ^ Input text (a lazy ByteString)+ -> LNode tag text+parseTreeThrowing mEnc bs = fst $ saxToTree $ parseSAXLocationsThrowing mEnc bs++-- | Strictly parse XML to tree. Returns error message or valid parsed tree.+parseTree' :: (GenericXMLString tag, GenericXMLString text) =>+ Maybe Encoding -- ^ Optional encoding override+ -> B.ByteString -- ^ Input text (a strict ByteString)+ -> Either XMLParseError (LNode tag text)+parseTree' mEnc bs = case parseTree mEnc (L.fromChunks [bs]) of+ (_, Just err) -> Left err+ (root, Nothing) -> Right root +
Text/XML/Expat/Format.hs view
@@ -102,13 +102,11 @@ B.concat [pack "</", gxToByteString name, B.singleton (c2w '>')]:putSAX elts putSAX (CharacterData txt:elts) = B.concat (escapeText (gxToByteString txt)):putSAX elts+putSAX (FailDocument _:elts) = putSAX elts putSAX [] = [] pack :: String -> B.ByteString pack = B.pack . map c2w--unpack :: L.ByteString -> String-unpack = map w2c . L.unpack escapees :: [Word8] escapees = map c2w "&<\"'"
Text/XML/Expat/IO.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE ForeignFunctionInterface #-}+ -- hexpat, a Haskell wrapper for expat -- Copyright (C) 2008 Evan Martin <martine@danga.com> -- Copyright (C) 2009 Stephen Blackheath <http://blacksapphire.com/antispam>@@ -101,7 +103,7 @@ unStatus :: CInt -> Bool unStatus 0 = False-unStatus 1 = True+unStatus _ = True -- |@parse data@ feeds /lazy/ ByteString data into a 'Parser'. It returns Nothing -- on success, or Just the parse error.@@ -348,20 +350,20 @@ writeIORef charRef $ wrapCharacterDataHandler parser handler pairwise (x1:x2:xs) = (x1,x2) : pairwise xs-pairwise [] = []+pairwise _ = [] -foreign import ccall unsafe "Text/XML/Expat/IO.chs.h XML_ParserCreate"+foreign import ccall unsafe "XML_ParserCreate" parserCreate'_ :: ((Ptr CChar) -> (IO (Ptr ()))) -foreign import ccall unsafe "Text/XML/Expat/IO.chs.h XML_SetStartElementHandler"+foreign import ccall unsafe "XML_SetStartElementHandler" xmlSetstartelementhandler :: ((Ptr ()) -> ((FunPtr ((Ptr ()) -> ((Ptr CChar) -> ((Ptr (Ptr CChar)) -> (IO ()))))) -> (IO ()))) -foreign import ccall unsafe "Text/XML/Expat/IO.chs.h XML_SetEndElementHandler"+foreign import ccall unsafe "XML_SetEndElementHandler" xmlSetendelementhandler :: ((Ptr ()) -> ((FunPtr ((Ptr ()) -> ((Ptr CChar) -> (IO ())))) -> (IO ()))) -foreign import ccall unsafe "Text/XML/Expat/IO.chs.h XML_SetCharacterDataHandler"+foreign import ccall unsafe "XML_SetCharacterDataHandler" xmlSetcharacterdatahandler :: ((Ptr ()) -> ((FunPtr ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (IO ()))))) -> (IO ()))) -foreign import ccall safe "Text/XML/Expat/IO.chs.h XML_Parse"+foreign import ccall safe "XML_Parse" doParseChunk'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (CInt -> (IO CInt)))))
Text/XML/Expat/Qualified.hs view
@@ -96,4 +96,3 @@ tag (QName (Just prefix) local) = prefix `mappend` gxFromChar ':' `mappend` local tag (QName Nothing local) = local -
Text/XML/Expat/Tree.hs view
@@ -91,6 +91,7 @@ UNode, UNodes, UAttributes,+ textContent, extractText, -- * Parse to tree parseTree,@@ -105,8 +106,9 @@ parseSAXLocations, -- * Variants that throw exceptions XMLParseException(..),- parseSAXThrowing, parseTreeThrowing,+ parseSAXThrowing,+ parseSAXLocationsThrowing, -- * Abstraction of string types GenericXMLString(..) ) where@@ -180,7 +182,7 @@ gxFromChar = T.singleton gxHead = T.head gxTail = T.tail- gxBreakOn c = T.break (==c)+ gxBreakOn c = T.breakBy (==c) gxFromCStringLen cstr = TE.decodeUtf8 <$> peekByteStringLen cstr gxToByteString = TE.encodeUtf8 @@ -225,9 +227,14 @@ -- | Extract all text content from inside a tag into a single string, including -- any text contained in children.+textContent :: Monoid text => Node tag text -> text+textContent (Element _ _ children) = mconcat $ map textContent children+textContent (Text txt) = txt++-- | Deprecated - renamed to textContent. extractText :: Monoid text => Node tag text -> text-extractText (Element _ _ children) = mconcat $ map extractText children-extractText (Text txt) = txt+{-# DEPRECATED extractText "renamed to textContent" #-}+extractText = textContent modifyChildren :: ([Node tag text] -> [Node tag text]) -> Node tag text@@ -276,9 +283,12 @@ start name attrs stack = Element name attrs [] : stack text str (cur:rest) = modifyChildren (Text str:) cur : rest+ text _ [] = impossible end (cur:parent:rest) = let node = modifyChildren reverse cur in modifyChildren (node:) parent : rest+ end _ = impossible+ impossible = error "parseTree' impossible" data SAXEvent tag text = StartElement tag [(tag, text)] |@@ -343,16 +353,6 @@ instance Exception XMLParseException where --- | Lazily parse XML to SAX events. In the event of an error, throw 'XMLParseException'.-parseSAXThrowing :: (GenericXMLString tag, GenericXMLString text) =>- Maybe Encoding -- ^ Optional encoding override- -> L.ByteString -- ^ Input text (a lazy ByteString)- -> [SAXEvent tag text]-parseSAXThrowing mEnc bs = map freakOut $ parseSAX mEnc bs- where- freakOut (FailDocument err) = Exc.throw $ XMLParseException err- freakOut other = other- -- | A variant of parseSAX that gives a document location with each SAX event. parseSAXLocations :: (GenericXMLString tag, GenericXMLString text) => Maybe Encoding -- ^ Optional encoding override@@ -395,6 +395,27 @@ return $ reverse queue ++ rem runParser $ L.toChunks input++-- | Lazily parse XML to SAX events. In the event of an error, throw 'XMLParseException'.+parseSAXThrowing :: (GenericXMLString tag, GenericXMLString text) =>+ Maybe Encoding -- ^ Optional encoding override+ -> L.ByteString -- ^ Input text (a lazy ByteString)+ -> [SAXEvent tag text]+parseSAXThrowing mEnc bs = map freakOut $ parseSAX mEnc bs+ where+ freakOut (FailDocument err) = Exc.throw $ XMLParseException err+ freakOut other = other++-- | A variant of parseSAX that gives a document location with each SAX event.+-- In the event of an error, throw 'XMLParseException'.+parseSAXLocationsThrowing :: (GenericXMLString tag, GenericXMLString text) =>+ Maybe Encoding -- ^ Optional encoding override+ -> L.ByteString -- ^ Input text (a lazy ByteString)+ -> [(SAXEvent tag text, XMLParseLocation)]+parseSAXLocationsThrowing mEnc bs = map freakOut $ parseSAXLocations mEnc bs+ where+ freakOut (FailDocument err, _) = Exc.throw $ XMLParseException err+ freakOut other = other -- | A lower level function that lazily converts a SAX stream into a tree structure. saxToTree :: GenericXMLString tag =>
hexpat.cabal view
@@ -1,6 +1,6 @@ Cabal-Version: >= 1.4 Name: hexpat-Version: 0.9+Version: 0.10 Synopsis: wrapper for expat, the fast XML parser Description: Expat (<http://expat.sourceforge.net/>) is a stream-oriented XML parser@@ -48,17 +48,17 @@ haskell98, bytestring, mtl >= 1.1.0.0,- text >= 0.1,+ text >= 0.5, utf8-string >= 0.3.3, parallel, containers, extensible-exceptions >= 0.1 && < 0.2 Exposed-Modules:+ Text.XML.Expat.Annotated, Text.XML.Expat.Tree, Text.XML.Expat.Format, Text.XML.Expat.Namespaced, Text.XML.Expat.Qualified, Text.XML.Expat.IO- Extensions: ForeignFunctionInterface Extra-Libraries: expat
test/tests.hs view
@@ -116,16 +116,16 @@ ["start open","start test1","end test1","start hello","end hello","end open"] l -test_extractText = do+test_textContent = do let tree = Element "cheese" [("type", "edam")] [Text "You don't actually ", Element "sub" [] [Text "have any "], Text "cheese at all", Text ", do you?"]- assertEqual "extractText" "You don't actually have any cheese at all, do you?" (extractText tree)+ assertEqual "textContent" "You don't actually have any cheese at all, do you?" (textContent tree) main = do- testXML <- readFile "test.xml"+ testXML <- map w2c . B.unpack <$> B.readFile "test.xml" -- Remove trailing newline let testXML' = reverse . dropWhile (== '\n') . reverse $ testXML docs = simpleDocs ++ [testXML']@@ -159,6 +159,6 @@ TestCase $ test_error3, TestCase $ test_error4, TestCase $ test_parse,- TestCase $ test_extractText+ TestCase $ test_textContent ]