xml-indexed-cursor-0.1.1.0: Indexed XML cursors similar to 'Text.XML.Cursor' from xml-conduit

Text.XML.Cursor.Indexed

Description

This module provides indexed Cursors. It has a very similar API to Text.XML.Cursor.

The big difference is in the Cursor type. Cursor wraps around a Node, while this module's Cursor type wraps around an IndexedNode.

An IndexedNode is a data type that contains both a Node and a NodeIndex. The NodeIndex gives a way to figure out how two IndexedNodes compare to each other in the Document. It gives the ability to figure out which IndexedNode comes earlier in the Document. This gives the ability to sort lists of IndexedNodes, based on their location in the Document. See NodeIndex for more information.

Synopsis

# Cursor

This is similar to Cursor except for IndexedNode.

This is similar to Axis except for IndexedNode.

# NodeIndex and IndexedNode

newtype NodeIndex Source #

Index for a Node in a Document.

The root element has a value of '[]'. Every child element is given an Int index as the first element of the list, and the grandchild elements are given an Int index as the second element of the list, and so on. If there are multiple root elements, then '[]' acts as a "virtual" root element that contains all actual root elements.

>>> let cursor = indexedCursorFromText_ "<foo><bar/></foo>"
>>> unNodeIndex $indexedCursorNodeIndex cursor fromList []  This function will be used in the following examples. >>> :{ let getNodeIndex :: [IndexedCursor] -> Seq Int getNodeIndex = unNodeIndex . indexedCursorNodeIndex . head :}  The index of the first child of the root be [0] >>> let cursor = indexedCursorFromText_ "<foo><bar/><baz/></foo>" >>> getNodeIndex$ child cursor
fromList [0]


The index of the second child of the root would be [1].

>>> let cursor = indexedCursorFromText_ "<foo><bar/><baz/></foo>"
>>> getNodeIndex $cursor$| child >=> followingSibling
fromList [1]


The index of the third child of the root would be [2].

>>> let cursor = indexedCursorFromText_ "<foo><bar/><baz/><zap/></foo>"
>>> getNodeIndex $cursor$| child >=> followingSibling >=> followingSibling
fromList [2]


The index of the first child of the first child of the root would be [0, 0].

>>> let cursor = indexedCursorFromText_ "<foo><bar><hello/></bar></foo>"
>>> getNodeIndex $cursor$| child >=> child
fromList [0,0]


The index of the second child of the first child of the root would be [0, 1] (since the [Int] is stored reversed).

>>> let cursor = indexedCursorFromText_ "<foo><bar><hello/><bye/></bar></foo>"
>>> getNodeIndex $cursor$| child >=> child >=> followingSibling
fromList [0,1]


The index of the third child of the fourth child of the root would be [3, 2].

>>> let doc = "<foo><zero/><one/><two/><three><sub0/><sub1/><sub2/></three></foo>"
>>> let cursor = indexedCursorFromText_ doc
>>> :{
let xpath =
child >=>                 -- focusing on <zero/>
followingSibling >=>      -- focusing on <one/>
followingSibling >=>      -- focusing on <two/>
followingSibling >=>      -- focusing on <three/>
child >=>             -- focusing on the <sub0/> element
followingSibling >=>  -- focusing on the <sub1/> element
followingSibling      -- focusing on the <sub2/> eleemnt
in getNodeIndex $xpath cursor :} fromList [3,2]  Constructors  NodeIndex FieldsunNodeIndex :: Seq Int Instances  Source # Methods Source # Methodsgfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> NodeIndex -> c NodeIndex #gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c NodeIndex #dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c NodeIndex) #dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c NodeIndex) #gmapT :: (forall b. Data b => b -> b) -> NodeIndex -> NodeIndex #gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> NodeIndex -> r #gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> NodeIndex -> r #gmapQ :: (forall d. Data d => d -> u) -> NodeIndex -> [u] #gmapQi :: Int -> (forall d. Data d => d -> u) -> NodeIndex -> u #gmapM :: Monad m => (forall d. Data d => d -> m d) -> NodeIndex -> m NodeIndex #gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> NodeIndex -> m NodeIndex #gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> NodeIndex -> m NodeIndex # Source # Methods Source # Methods Source # MethodsshowList :: [NodeIndex] -> ShowS # Source # MethodsnodeIndexLens :: Functor f => (NodeIndex -> f NodeIndex) -> NodeIndex -> f NodeIndex Source # class HasNodeIndex a where Source # Minimal complete definition nodeIndexLens Methods nodeIndexLens :: Functor f => (NodeIndex -> f NodeIndex) -> a -> f a Source # This is basically Lens' a NodeIndex. Instances  Source # MethodsnodeIndexLens :: Functor f => (NodeIndex -> f NodeIndex) -> IndexedNode -> f IndexedNode Source # Source # MethodsnodeIndexLens :: Functor f => (NodeIndex -> f NodeIndex) -> NodeIndex -> f NodeIndex Source # Index to use for the root NodeIndex. Should be '[]'. IndexedNode just wraps together a Node and a NodeIndex for that Node. Constructors  IndexedNode Fields Instances  Source # Methods Source # Methodsgfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> IndexedNode -> c IndexedNode #gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c IndexedNode #dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c IndexedNode) #dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c IndexedNode) #gmapT :: (forall b. Data b => b -> b) -> IndexedNode -> IndexedNode #gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> IndexedNode -> r #gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> IndexedNode -> r #gmapQ :: (forall d. Data d => d -> u) -> IndexedNode -> [u] #gmapQi :: Int -> (forall d. Data d => d -> u) -> IndexedNode -> u #gmapM :: Monad m => (forall d. Data d => d -> m d) -> IndexedNode -> m IndexedNode #gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> IndexedNode -> m IndexedNode #gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> IndexedNode -> m IndexedNode # Source # MethodsshowList :: [IndexedNode] -> ShowS # Source # MethodsnodeIndexLens :: Functor f => (NodeIndex -> f NodeIndex) -> IndexedNode -> f IndexedNode Source # Get the NodeIndex from the IndexedNode pointed to by an IndexedCursor. Convert a Node to a root IndexedNode. Arguments  :: NodeIndex Parent NodeIndex. -> Int Child index. -> NodeIndex Create a NodeIndex for the Int child below the input parent NodeIndex. Given a NodeIndex, create an IndexedNode for a Node. In childNodeToIndexedNode parentIndex childIndexInt childNode, create an IndexedNode out of childNode, creating its NodeIndex using toChildIndex. In childNodesToIndexedNodes parentIndex childNodes convert a list of Node childNodes to a list of IndexNodes using the NodeIndex parentIndex. # Converting Convert a Document to a Cursor. It will point to the document root. Convert a Node to a root IndexedCursor. Arguments  :: (node -> [node]) get children -> node -> Cursor node node :: Cursor node -> node # The current node. # Generic functions re-exported from Text.XML.Cursor.Generic child :: Cursor node -> [Cursor node] # The child axis. XPath: the child axis contains the children of the context node. parent :: Axis node # The parent axis. As described in XPath: the parent axis contains the parent of the context node, if there is one. Every node but the root element of the document has a parent. Parent nodes will always be NodeElements. precedingSibling :: Axis node # The preceding-sibling axis. XPath: the preceding-sibling axis contains all the preceding siblings of the context node [...]. followingSibling :: Axis node # The following-sibling axis. XPath: the following-sibling axis contains all the following siblings of the context node [...]. ancestor :: Axis node # The ancestor axis. XPath: the ancestor axis contains the ancestors of the context node; the ancestors of the context node consist of the parent of context node and the parent's parent and so on; thus, the ancestor axis will always include the root node, unless the context node is the root node. descendant :: Axis node # The descendant axis. XPath: the descendant axis contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus the descendant axis never contains attribute or namespace nodes. orSelf :: Axis node -> Axis node # Modify an axis by adding the context node itself as the first element of the result list. preceding :: Axis node # The preceding axis. XPath: the preceding axis contains all nodes in the same document as the context node that are before the context node in document order, excluding any ancestors and excluding attribute nodes and namespace nodes. following :: Axis node # The following axis. XPath: the following axis contains all nodes in the same document as the context node that are after the context node in document order, excluding any descendants and excluding attribute nodes and namespace nodes. # Generic operators re-exported from Text.XML.Cursor.Generic (&|) :: (Cursor node -> [a]) -> (a -> b) -> Cursor node -> [b] infixr 1 # Apply a function to the result of an axis. (&/) :: Axis node -> (Cursor node -> [a]) -> Cursor node -> [a] infixr 1 # Combine two axes so that the second works on the children of the results of the first. (&//) :: Axis node -> (Cursor node -> [a]) -> Cursor node -> [a] infixr 1 # Combine two axes so that the second works on the descendants of the results of the first. (&.//) :: Axis node -> (Cursor node -> [a]) -> Cursor node -> [a] infixr 1 # Combine two axes so that the second works on both the result nodes, and their descendants. ($|) :: Cursor node -> (Cursor node -> a) -> a infixr 1 #

Apply an axis to a 'Cursor node'.

($/) :: Cursor node -> (Cursor node -> [a]) -> [a] infixr 1 # Apply an axis to the children of a 'Cursor node'. ($//) :: Cursor node -> (Cursor node -> [a]) -> [a] infixr 1 #

Apply an axis to the descendants of a 'Cursor node'.

($.//) :: Cursor node -> (Cursor node -> [a]) -> [a] infixr 1 # Apply an axis to a 'Cursor node' as well as its descendants. (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c infixr 1 # Left-to-right Kleisli composition of monads. # "check" functions for IndexedCursor check :: Boolean b => (Cursor a -> b) -> Axis a Source # Filter cursors that don't pass a check. checkIndexedNode :: Boolean b => (IndexedNode -> b) -> IndexedAxis Source # Filter nodes that don't pass a check. checkElement :: Boolean b => (Element -> b) -> IndexedAxis Source # Filter elements that don't pass a check, and remove all non-elements. checkName :: Boolean b => (Name -> b) -> IndexedAxis Source # Filter elements that don't pass a name check, and remove all non-elements. # XPath-style functions for IndexedCursor Select only those elements with a matching tag name. XPath: /A node test that is a QName is true if and only if the type of the node (see [5 Data Model]) is the principal node type and has an expanded-name equal to the expanded-name specified by the QName./ Select only text nodes, and directly give the Content values. XPath: The node test text() is true for any text node. Note that this is not strictly an Axis, but will work with most combinators. >>> let cursor = indexedCursorFromText_ "<foo>hello<bar/>bye</foo>" >>> cursor$| child >=> content
["hello","bye"]
>>> cursor $| child >=> child >=> content []  Select attributes on the current element (or nothing if it is not an element). XPath: /the attribute axis contains the attributes of the context node; the axis will be empty unless the context node is an element/ Note that this is not strictly an Axis, but will work with most combinators. The return list of the generalised axis contains as elements lists of Content elements, each full list representing an attribute value. >>> let cursor = indexedCursorFromText_ "<foo hello='cat' bar='3'>hello world</foo>" >>> cursor$| attribute "hello"
["cat"]
>>> cursor $| attribute "doesntexist" [] >>> cursor$| child >=> attribute "attroftext"
[]


Similar to attribute but return a Maybe instead of a list.

>>> let cursor = indexedCursorFromText_ "<foo hello='cat' bar='3'>hello world</foo>"
>>> cursor $| attributeMay "hello" Just "cat" >>> cursor$| attributeMay "doesntexist"
Nothing


Select attributes on the current element (or nothing if it is not an element). Namespace and case are ignored.

XPath: /the attribute axis contains the attributes of the context node; the axis will be empty unless the context node is an element/

Note that this is not strictly an Axis, but will work with most combinators.

The return list of the generalised axis contains as elements lists of Content elements, each full list representing an attribute value.

>>> let cursor = indexedCursorFromText_ "<foo HellO='cat'/>"
>>> cursor $| laxAttribute "HellO" ["cat"] >>> cursor$| laxAttribute "Hello"
["cat"]
>>> cursor $| laxAttribute "hello" ["cat"] >>> cursor$| laxAttribute "bye"
[]


Select only those element nodes with the given attribute.

Select only those element nodes containing the given attribute key/value pair.

For a given Name, find all descendant Elements with that Name.

For a given Name, find all ancestor Elements. with that Name.

In descendantElementsNamedWithAttr elemName attrKey attrVal, find all descendant Elements with elemName that have an attribute called attrKey with a value of attrVal.

Find all content in all descendants.

>>> let cursor = indexedCursorFromText_ "<foo>hello<bar>lala</bar>bye</foo>"
>>> descendantContent cursor
["hello","lala","bye"]

>>> let cursor = indexedCursorFromText_ "<foo/>"
>>> descendantContent cursor
[]


Find attribute with Name on the element IndexedCursor is pointing to.

>>> let cursor = indexedCursorFromText_ "<foo hello='3'/>"
>>> attrValForElemCursor "hello" cursor
Just "3"
>>> attrValForElemCursor "bye" cursor
Nothing


# Parse directly into IndexedCursor

This reads a Document from a ByteString with parseLBS_, and then converts that Document to an IndexedCursor.

Similar to indexedCursorFromByteString_ but uses parseLBS instead of parseLBS_.

Similar to indexedCursorFromByteString_ but uses parseText_ instead of parseLBS_.

Similar to indexedCursorFromByteString_ but uses parseText instead of parseLBS_.

Similar to indexedCursorFromByteString_ but also takes ParseSettings.

Similar to indexedCursorFromByteString but also takes ParseSettings.

Similar to indexedCursorFromText_ but also takes ParseSettings.

Similar to indexedCursorFromText but also takes ParseSettings.