Text.XML.Stream.Parse

xml-conduit-1.10.0.0: Pure-Haskell utilities for dealing with XML with the conduit package.

Safe Haskell | None
Language | Haskell2010

Text.XML.Stream.Parse

Contents

- Parsing XML files
  - Parser settings
    - Entity decoding
- Event parsing
- Ignoring tags/trees
- Streaming events
- Tag name matching
- Attribute parsing
- Combinators
- Streaming combinators
- Exceptions
- Other types

Description

This module provides both a native Haskell solution for parsing XML documents into a stream of events, and a set of parser combinators for dealing with a stream of events.

As a simple example:

    >>> :set -XOverloadedStrings
    >>> import Conduit (runConduit, (.|))
    >>> import Data.Text (Text, unpack)
    >>> import Data.XML.Types (Event)
    >>> data Person = Person Int Text Text deriving Show
    >>> :{
    let parsePerson :: MonadThrow m => ConduitT Event o m (Maybe Person)
        parsePerson = tag' "person" parseAttributes $ \(age, goodAtHaskell) -> do
          name <- content
          return $ Person (read $ unpack age) name goodAtHaskell
          where parseAttributes = (,) <$> requireAttr "age" <*> requireAttr "goodAtHaskell" <* ignoreAttrs
        parsePeople :: MonadThrow m => ConduitT Event o m (Maybe [Person])
        parsePeople = tagNoAttr "people" $ many parsePerson
        inputXml = mconcat
          [ "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
          , "<people>"
          , "  <person age=\"25\" goodAtHaskell=\"yes\">Michael</person>"
          , "  <person age=\"2\" goodAtHaskell=\"might become\">Eliezer</person>"
          , "</people>"
          ]
    :}

    >>> runConduit $ parseLBS def inputXml .| force "people required" parsePeople
    [Person 25 "Michael" "yes",Person 2 "Eliezer" "might become"]

This module also supports streaming results using `yield`. This allows parser results to be processed using conduits while a particular parser (e.g. `many`) is still running. Without using streaming results, you have to wait until the parser finished before you can process the result list. Large XML files might be easier to process by using streaming results. See http://stackoverflow.com/q/21367423/2597135 for a related discussion.

    >>> import Data.Conduit.List as CL
    >>> :{
    let parsePeople' :: MonadThrow m => ConduitT Event Person m (Maybe ())
        parsePeople' = tagNoAttr "people" $ manyYield parsePerson
    :}

    >>> runConduit $ parseLBS def inputXml .| force "people required" parsePeople' .| CL.mapM_ print
    Person 25 "Michael" "yes"
    Person 2 "Eliezer" "might become"

Previous versions of this module contained a number of more sophisticated functions written by Aristid Breitkreuz and Dmitry Olshansky. To keep this package simpler, those functions are being moved to a separate package. This note will be updated with the name of the package(s) when available.

Synopsis

- parseBytes :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT ByteString Event m ()
- parseBytesPos :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT ByteString EventPos m ()
- parseText :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT Text Event m ()
- parseTextPos :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT Text EventPos m ()
- detectUtf :: forall (m :: Type -> Type). MonadThrow m => ConduitT ByteString Text m ()
- parseFile :: forall (m :: Type -> Type) i. MonadResource m => ParseSettings -> FilePath -> ConduitT i Event m ()
- parseLBS :: forall (m :: Type -> Type) i. MonadThrow m => ParseSettings -> ByteString -> ConduitT i Event m ()
- data ParseSettings
- def :: Default a => a
- type DecodeEntities = Text -> Content
- type DecodeIllegalCharacters = Int -> Maybe Char
- psDecodeEntities :: ParseSettings -> DecodeEntities
- psDecodeIllegalCharacters :: ParseSettings -> DecodeIllegalCharacters
- psRetainNamespaces :: ParseSettings -> Bool
- psEntityExpansionSizeLimit :: ParseSettings -> Int
- psIgnoreInternalEntityDeclarations :: ParseSettings -> Bool
- decodeXmlEntities :: DecodeEntities
- decodeHtmlEntities :: DecodeEntities
- tag :: forall (m :: Type -> Type) a b o c. MonadThrow m => NameMatcher a -> (a -> AttrParser b) -> (b -> ConduitT Event o m c) -> ConduitT Event o m (Maybe c)
- tag' :: forall (m :: Type -> Type) a b o c. MonadThrow m => NameMatcher a -> AttrParser b -> (b -> ConduitT Event o m c) -> ConduitT Event o m (Maybe c)
- tagNoAttr :: forall (m :: Type -> Type) a o b. MonadThrow m => NameMatcher a -> ConduitT Event o m b -> ConduitT Event o m (Maybe b)
- tagIgnoreAttrs :: forall (m :: Type -> Type) a o b. MonadThrow m => NameMatcher a -> ConduitT Event o m b -> ConduitT Event o m (Maybe b)
- content :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m Text
- contentMaybe :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m (Maybe Text)
- ignoreEmptyTag :: forall (m :: Type -> Type) a o. MonadThrow m => NameMatcher a -> ConduitT Event o m (Maybe ())
- ignoreTree :: forall (m :: Type -> Type) a b o. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event o m (Maybe ())
- ignoreContent :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m (Maybe ())
- ignoreTreeContent :: forall (m :: Type -> Type) a b o. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event o m (Maybe ())
- ignoreAnyTreeContent :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m (Maybe ())
- takeContent :: forall (m :: Type -> Type). MonadThrow m => ConduitT Event Event m (Maybe ())
- takeTree :: forall (m :: Type -> Type) a b. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ())
- takeTreeContent :: forall (m :: Type -> Type) a b. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ())
- takeAnyTreeContent :: forall (m :: Type -> Type). MonadThrow m => ConduitT Event Event m (Maybe ())
- newtype NameMatcher a = NameMatcher {
  - runNameMatcher :: Name -> Maybe a
  }
- matching :: (Name -> Bool) -> NameMatcher Name
- anyOf :: [Name] -> NameMatcher Name
- anyName :: NameMatcher Name
- data AttrParser a
- attr :: Name -> AttrParser (Maybe Text)
- requireAttr :: Name -> AttrParser Text
- optionalAttr :: Name -> AttrParser (Maybe Text)
- requireAttrRaw :: String -> ((Name, [Content]) -> Maybe b) -> AttrParser b
- optionalAttrRaw :: ((Name, [Content]) -> Maybe b) -> AttrParser (Maybe b)
- ignoreAttrs :: AttrParser ()
- orE :: forall (m :: Type -> Type) o a. Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe a)
- choose :: forall (m :: Type -> Type) o a. Monad m => [ConduitT Event o m (Maybe a)] -> ConduitT Event o m (Maybe a)
- many :: forall (m :: Type -> Type) o a. Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m [a]
- many_ :: forall (m :: Type -> Type) o a. MonadThrow m => ConduitT Event o m (Maybe a) -> ConduitT Event o m ()
- manyIgnore :: forall (m :: Type -> Type) o a b. Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe b) -> ConduitT Event o m [a]
- many' :: forall (m :: Type -> Type) o a. MonadThrow m => ConduitT Event o m (Maybe a) -> ConduitT Event o m [a]
- force :: MonadThrow m => String -> m (Maybe a) -> m a
- manyYield :: forall (m :: Type -> Type) a b. Monad m => ConduitT a b m (Maybe b) -> ConduitT a b m ()
- manyYield' :: forall (m :: Type -> Type) b. MonadThrow m => ConduitT Event b m (Maybe b) -> ConduitT Event b m ()
- manyIgnoreYield :: forall (m :: Type -> Type) b. MonadThrow m => ConduitT Event b m (Maybe b) -> ConduitT Event b m (Maybe ()) -> ConduitT Event b m ()
- data XmlException
  - = XmlException {
    - xmlErrorMessage :: String
    - xmlBadInput :: Maybe Event
    }
  - | InvalidEndElement Name (Maybe Event)
  - | InvalidEntity String (Maybe Event)
  - | MissingAttribute String
  - | UnparsedAttributes [(Name, [Content])]
- data PositionRange
- type EventPos = (Maybe PositionRange, Event)

# Parsing XML files

parseBytes :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT ByteString Event m () #

Parses a byte stream into `Event`s. This function is implemented fully in Haskell using attoparsec-text for parsing. The produced error messages do not give line/column information, so you may prefer to stick with the parser provided by libxml-enumerator. However, this has the advantage of not relying on any C libraries.

This relies on `detectUtf` to determine character encoding, and `parseText` to do the actual parsing.

parseBytesPos :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT ByteString EventPos m () #

parseText :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT Text Event m () #

Parses a character stream into `Event`s. This function is implemented fully in Haskell using attoparsec-text for parsing. The produced error messages do not give line/column information, so you may prefer to stick with the parser provided by libxml-enumerator. However, this has the advantage of not relying on any C libraries.

Since 1.2.4

parseTextPos :: forall (m :: Type -> Type). MonadThrow m => ParseSettings -> ConduitT Text EventPos m () #

Same as `parseText`, but includes the position of each event.

Since 1.2.4

detectUtf :: forall (m :: Type -> Type). MonadThrow m => ConduitT ByteString Text m () #

Automatically determine which UTF variant is being used. This function first checks for BOMs, removing them as necessary, and then check for the equivalent of <?xml for each of UTF-8, UTF-16LEBE, and UTF-32LEBE. It defaults to assuming UTF-8.

parseFile :: forall (m :: Type -> Type) i. MonadResource m => ParseSettings -> FilePath -> ConduitT i Event m () #

A helper function which reads a file from disk using `enumFile`, detects character encoding using `detectUtf`, parses the XML using `parseBytes`, and then hands off control to your supplied parser.

parseLBS :: forall (m :: Type -> Type) i. MonadThrow m => ParseSettings -> ByteString -> ConduitT i Event m () #

Parse an event stream from a lazy `ByteString`.

## Parser settings

data ParseSettings #

#### Instances

Instances details

Default ParseSettings # |
Instance details Defined in Text.XML.Stream.Parse Methods def :: ParseSettings #

def :: Default a => a #

The default value for this type.

type DecodeEntities = Text -> Content #

type DecodeIllegalCharacters = Int -> Maybe Char #

psDecodeEntities :: ParseSettings -> DecodeEntities #

psDecodeIllegalCharacters :: ParseSettings -> DecodeIllegalCharacters #

How to decode illegal character references (`&#[0-9]+;` or `&#x[0-9a-fA-F]+;`).

Character references within the legal ranges defined by the standard are automatically parsed. Others are passed to this function.

Default: `const Nothing`

Since 1.7.1

psRetainNamespaces :: ParseSettings -> Bool #

Whether the original xmlns attributes should be retained in the parsed values. For more information on motivation, see:

https://github.com/snoyberg/xml/issues/38

Default: False

Since 1.2.1

psEntityExpansionSizeLimit :: ParseSettings -> Int #

Maximum number of characters allowed in expanding an internal entity. This is intended to protect against the billion laughs attack.

Default: `8192`

Since 1.9.1

psIgnoreInternalEntityDeclarations :: ParseSettings -> Bool #

Whether to resolve any but the predefined entities.

Default: `False`

### Entity decoding

decodeXmlEntities :: DecodeEntities #

Default implementation of `DecodeEntities`, which leaves the entity as-is. Numeric character references and the five standard entities (lt, gt, amp, quot, pos) are handled internally by the parser.

decodeHtmlEntities :: DecodeEntities #

HTML4-compliant entity decoder. Handles the additional 248 entities defined by HTML 4 and XHTML 1.

Note that HTML 5 introduces a drastically larger number of entities, and this code does not recognize most of them.

# Event parsing

tag #

Arguments

:: forall (m :: Type -> Type) a b o c. MonadThrow m |
=> NameMatcher a | Check if this is a correct tag name and return a value that can be used to get an `AttrParser`. If this fails, the function will return `Nothing`
-> (a -> AttrParser b) | Given the value returned by the name checker, this function will be used to get an `AttrParser` appropriate for the specific tag. If the `AttrParser` fails, the function will also return `Nothing`
-> (b -> ConduitT Event o m c) | Handler function to handle the attributes and children of a tag, given the value return from the `AttrParser`
-> ConduitT Event o m (Maybe c) |

The most generic way to parse a tag. It takes a `NameMatcher` to check whether this is a correct tag name, an `AttrParser` to handle attributes, and then a parser to deal with content.

`Events` are consumed if and only if the tag name and its attributes match.

This function automatically absorbs its balancing closing tag, and will throw an exception if not all of the attributes or child elements are consumed. If you want to allow extra attributes, see `ignoreAttrs`.

This function automatically ignores comments, instructions and whitespace.

tag' :: forall (m :: Type -> Type) a b o c. MonadThrow m => NameMatcher a -> AttrParser b -> (b -> ConduitT Event o m c) -> ConduitT Event o m (Maybe c) #

A simplified version of `tag` where the `NameMatcher` result isn't forwarded to the attributes parser.

Since 1.5.0

tagNoAttr #

Arguments

:: forall (m :: Type -> Type) a o b. MonadThrow m |
=> NameMatcher a | Check if this is a correct tag name
-> ConduitT Event o m b | Handler function to handle the children of the matched tag
-> ConduitT Event o m (Maybe b) |

A further simplified tag parser, which requires that no attributes exist.

tagIgnoreAttrs #

Arguments

:: forall (m :: Type -> Type) a o b. MonadThrow m |
=> NameMatcher a | Check if this is a correct tag name
-> ConduitT Event o m b | Handler function to handle the children of the matched tag
-> ConduitT Event o m (Maybe b) |

A further simplified tag parser, which ignores all attributes, if any exist

content :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m Text #

Grabs the next piece of content. If none if available, returns `empty`. This is simply a wrapper around `contentMaybe`.

contentMaybe :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m (Maybe Text) #

Grabs the next piece of content if available. This function skips over any comments, instructions or entities, and concatenates all content until the next start or end tag.

# Ignoring tags/trees

ignoreEmptyTag #

Arguments

:: forall (m :: Type -> Type) a o. MonadThrow m |
=> NameMatcher a | Check if this is a correct tag name
-> ConduitT Event o m (Maybe ()) |

Ignore an empty tag and all of its attributes. This does not ignore the tag recursively (i.e. it assumes there are no child elements). This function returns `Just ()` if the tag matched.

Since 1.5.0

ignoreTree :: forall (m :: Type -> Type) a b o. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event o m (Maybe ()) #

Same as `takeTree`, without yielding `Event`s.

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| (ignoreTree "a" ignoreAttrs >> sinkList)
    [EventBeginElement (Name {nameLocalName = "b", ...}) [],EventEndElement (Name {nameLocalName = "b", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "<a>content</a>" .| (ignoreTree "b" ignoreAttrs >> sinkList)
    [EventBeginElement (Name {nameLocalName = "a", ...}) [],EventContent (ContentText "content"),EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "content<a></a>" .| (ignoreTree anyName ignoreAttrs >> sinkList)
    [EventContent (ContentText "content"),EventBeginElement (Name {nameLocalName = "a", ...}) [],EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

Since 1.9.0

ignoreContent :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m (Maybe ()) #

Same as `takeContent`, without yielding `Event`s.

    >>> runConduit $ parseLBS def "<a>content</a>" .| (ignoreContent >> sinkList)
    [EventBeginElement (Name {nameLocalName = "a", ...}) [],EventContent (ContentText "content"),EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "content<a></a>" .| (ignoreContent >> sinkList)
    [EventBeginElement (Name {nameLocalName = "a", ...}) [],EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "content<a></a>" .| (ignoreContent >> sinkList)
    [EventBeginElement (Name {nameLocalName = "a", ...}) [],EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

Since 1.9.0

ignoreTreeContent :: forall (m :: Type -> Type) a b o. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event o m (Maybe ()) #

Same as `takeTreeContent`, without yielding `Event`s.

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| (ignoreTreeContent "a" ignoreAttrs >> sinkList)
    [EventBeginElement (Name {nameLocalName = "b", ...}) [],EventEndElement (Name {nameLocalName = "b", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "<a>content</a>" .| (ignoreTreeContent "b" ignoreAttrs >> sinkList)
    [EventBeginElement (Name {nameLocalName = "a", ...}) [],EventContent (ContentText "content"),EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "content<a></a>" .| (ignoreTreeContent anyName ignoreAttrs >> sinkList)
    [EventBeginElement (Name {nameLocalName = "a", ...}) [],EventEndElement (Name {nameLocalName = "a", ...}),EventEndDocument]

Since 1.5.0

ignoreAnyTreeContent :: forall (m :: Type -> Type) o. MonadThrow m => ConduitT Event o m (Maybe ()) #

Same as `takeAnyTreeContent`, without yielding `Event`s.

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| (ignoreAnyTreeContent >> sinkList)
    [EventBeginElement (Name {nameLocalName = "b", ...}) [],EventEndElement (Name {nameLocalName = "b", ...}),EventEndDocument]

    >>> runConduit $ parseLBS def "text<b></b>" .| (ignoreAnyTreeContent >> sinkList)
    [EventBeginElement (Name {nameLocalName = "b", ...}) [],EventEndElement (Name {nameLocalName = "b", ...}),EventEndDocument]

Since 1.5.0

# Streaming events

takeContent :: forall (m :: Type -> Type). MonadThrow m => ConduitT Event Event m (Maybe ()) #

Stream a single content `Event`.

Returns `Just ()` if a content `Event` was consumed, `Nothing` otherwise.

    >>> runConduit $ parseLBS def "content<a></a>" .| void takeContent .| sinkList
    [EventBeginDocument,EventContent (ContentText "content")]

If next event isn't a content, nothing is consumed.

    >>> runConduit $ parseLBS def "<a>content</a>" .| void takeContent .| sinkList
    [EventBeginDocument]

Since 1.5.0

takeTree :: forall (m :: Type -> Type) a b. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ()) #

Stream `Event`s corresponding to a single XML element that matches given `NameMatcher` and `AttrParser`, from the opening- to the closing-tag.

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| void (takeTree "a" ignoreAttrs) .| sinkList
    [EventBeginDocument,EventBeginElement (Name {nameLocalName = "a", ...}) [],EventContent (ContentText "content"),EventEndElement (Name {nameLocalName = "a", ...})]

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| void (takeTree "b" ignoreAttrs) .| sinkList
    [EventBeginDocument]

If next `Event` isn't an element, nothing is consumed.

    >>> runConduit $ parseLBS def "text<a></a>" .| void (takeTree "a" ignoreAttrs) .| sinkList
    [EventBeginDocument]

If an opening-tag is consumed but no matching closing-tag is found, an `XmlException` is thrown.

    >>> runConduit $ parseLBS def "<a><b></b>" .| void (takeTree "a" ignoreAttrs) .| sinkList
    *** Exception: InvalidEndElement (Name {nameLocalName = "a", nameNamespace = Nothing, namePrefix = Nothing}) Nothing

This function automatically ignores comments, instructions and whitespace.

Returns `Just ()` if an element was consumed, `Nothing` otherwise.

Since 1.5.0

takeTreeContent :: forall (m :: Type -> Type) a b. MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ()) #

Like `takeTree`, but can also stream a content `Event`.

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| void (takeTreeContent "a" ignoreAttrs) .| sinkList
    [EventBeginDocument,EventBeginElement (Name {nameLocalName = "a", ...}) [],EventContent (ContentText "content"),EventEndElement (Name {nameLocalName = "a", ...})]

    >>> runConduit $ parseLBS def "<a>content</a><b></b>" .| void (takeTreeContent "b" ignoreAttrs) .| sinkList
    [EventBeginDocument]

    >>> runConduit $ parseLBS def "content<a></a><b></b>" .| void (takeTreeContent "a" ignoreAttrs) .| sinkList
    [EventBeginDocument,EventContent (ContentText "content")]

Since 1.5.0

takeAnyTreeContent :: forall (m :: Type -> Type). MonadThrow m => ConduitT Event Event m (Maybe ()) #

Like `takeTreeContent`, without checking for tag name or attributes.

    >>> runConduit $ parseLBS def "text<a></a>" .| void takeAnyTreeContent .| sinkList
    [EventBeginDocument,EventContent (ContentText "text")]

    >>> runConduit $ parseLBS def "</a><b></b>" .| void takeAnyTreeContent .| sinkList
    [EventBeginDocument]

    >>> runConduit $ parseLBS def "<b><c></c></b></a>text" .| void takeAnyTreeContent .| sinkList
    [EventBeginDocument,EventBeginElement (Name {nameLocalName = "b", ...}) [],EventBeginElement (Name {nameLocalName = "c", ...}) [],EventEndElement (Name {nameLocalName = "c", ...}),EventEndElement (Name {nameLocalName = "b", ...})]

Since 1.5.0

# Tag name matching

newtype NameMatcher a #

A `NameMatcher` describes which names a tag parser is allowed to match.

Since 1.5.0

Constructors

NameMatcher |
Fields runNameMatcher :: Name -> Maybe a

#### Instances

Instances details

Alternative NameMatcher # | `NameMatcher`s can be combined with `<|>`
Instance details Defined in Text.XML.Stream.Parse Methods empty :: NameMatcher a # (<|>) :: NameMatcher a -> NameMatcher a -> NameMatcher a # some :: NameMatcher a -> NameMatcher [a] # many :: NameMatcher a -> NameMatcher [a] #
Applicative NameMatcher # |
Instance details Defined in Text.XML.Stream.Parse Methods pure :: a -> NameMatcher a # (<*>) :: NameMatcher (a -> b) -> NameMatcher a -> NameMatcher b # liftA2 :: (a -> b -> c) -> NameMatcher a -> NameMatcher b -> NameMatcher c # (*>) :: NameMatcher a -> NameMatcher b -> NameMatcher b # (<*) :: NameMatcher a -> NameMatcher b -> NameMatcher a #
Functor NameMatcher # |
Instance details Defined in Text.XML.Stream.Parse Methods fmap :: (a -> b) -> NameMatcher a -> NameMatcher b # (<$) :: a -> NameMatcher b -> NameMatcher a #
a ~ Name => IsString (NameMatcher a) # | Match a single `Name` in a concise way. Note that `Name` is namespace sensitive: when using the `IsString` instance, use `"{http://a/b}c"` to match the tag `c` in the XML namespace `http://a/b`
Instance details Defined in Text.XML.Stream.Parse Methods fromString :: String -> NameMatcher a #

matching :: (Name -> Bool) -> NameMatcher Name #

`matching f` matches `name` iff `f name` is true. Returns the matched `Name`.

Since 1.5.0

anyOf :: [Name] -> NameMatcher Name #

Matches any `Name` from the given list. Returns the matched `Name`.

Since 1.5.0

anyName :: NameMatcher Name #

Matches any `Name`. Returns the matched `Name`.

Since 1.5.0

# Attribute parsing

data AttrParser a #

A monad for parsing attributes. By default, it requires you to deal with all attributes present on an element, and will throw an exception if there are unhandled attributes. Use the `requireAttr`, `attr` et al functions for handling an attribute, and `ignoreAttrs` if you would like to skip the rest of the attributes on an element.

`Alternative` instance behaves like `First` monoid: it chooses first parser which doesn't fail.

#### Instances

Instances details

MonadThrow AttrParser # |
Instance details Defined in Text.XML.Stream.Parse Methods throwM :: (HasCallStack, Exception e) => e -> AttrParser a #
Alternative AttrParser # |
Instance details Defined in Text.XML.Stream.Parse Methods empty :: AttrParser a # (<|>) :: AttrParser a -> AttrParser a -> AttrParser a # some :: AttrParser a -> AttrParser [a] # many :: AttrParser a -> AttrParser [a] #
Applicative AttrParser # |
Instance details Defined in Text.XML.Stream.Parse Methods pure :: a -> AttrParser a # (<*>) :: AttrParser (a -> b) -> AttrParser a -> AttrParser b # liftA2 :: (a -> b -> c) -> AttrParser a -> AttrParser b -> AttrParser c # (*>) :: AttrParser a -> AttrParser b -> AttrParser b # (<*) :: AttrParser a -> AttrParser b -> AttrParser a #
Functor AttrParser # |
Instance details Defined in Text.XML.Stream.Parse Methods fmap :: (a -> b) -> AttrParser a -> AttrParser b # (<$) :: a -> AttrParser b -> AttrParser a #
Monad AttrParser # |
Instance details Defined in Text.XML.Stream.Parse Methods (>>=) :: AttrParser a -> (a -> AttrParser b) -> AttrParser b # (>>) :: AttrParser a -> AttrParser b -> AttrParser b # return :: a -> AttrParser a #

attr :: Name -> AttrParser (Maybe Text) #

Return the value for an attribute if present.

requireAttr :: Name -> AttrParser Text #

Shortcut composition of `force` and `attr`.

optionalAttr :: Name -> AttrParser (Maybe Text) #

Deprecated: Please use `attr`.

requireAttrRaw :: String -> ((Name, [Content]) -> Maybe b) -> AttrParser b #

optionalAttrRaw :: ((Name, [Content]) -> Maybe b) -> AttrParser (Maybe b) #

ignoreAttrs :: AttrParser () #

Skip the remaining attributes on an element. Since this will clear the list of attributes, you must call this after any calls to `requireAttr`, `optionalAttr`, etc.

# Combinators

orE #

Arguments

:: forall (m :: Type -> Type) o a. Monad m |
=> ConduitT Event o m (Maybe a) | The first (preferred) parser
-> ConduitT Event o m (Maybe a) | The second parser, only executed if the first parser fails
-> ConduitT Event o m (Maybe a) |

Get the value of the first parser which returns `Just`. If no parsers succeed (i.e., return `Just`), this function returns `Nothing`.

    orE a b = choose [a, b]

Warning: `orE` doesn't backtrack. See `choose` for detailed explanation.

choose #

Arguments

:: forall (m :: Type -> Type) o a. Monad m |
=> [ConduitT Event o m (Maybe a)] | List of parsers that will be tried in order.
-> ConduitT Event o m (Maybe a) | Result of the first parser to succeed, or `Nothing` if no parser succeeded

Get the value of the first parser which returns `Just`. If no parsers succeed (i.e., return `Just`), this function returns `Nothing`.

Warning: `choose` doesn't backtrack. If a parser consumed some events, subsequent parsers will continue from the following events. This can be a problem if parsers share an accepted prefix of events, so an earlier (failing) parser will discard the events that the later parser could potentially succeed on.

An other problematic case is using `choose` to implement order-independent parsing using a set of parsers, with a final trailing ignore-anything-else action. In this case, certain trees might be skipped.

    >>> :{
    let parse2Tags name1 name2 = do
          tag1 <- tagNoAttr name1 (pure ())
          tag2 <- tagNoAttr name2 (pure tag1)
          return $ join tag2
    :}

    >>> :{
    runConduit $ parseLBS def "<a></a><b></b>" .| choose
      [ parse2Tags "a" "b"
      , parse2Tags "a" "c"
      ]
    :}
    Just ()

    >>> :{
    runConduit $ parseLBS def "<a></a><b></b>" .| choose
      [ parse2Tags "a" "c"
      , parse2Tags "a" "b"
      ]
    :}
    Nothing

many :: forall (m :: Type -> Type) o a. Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m [a] #

Keep parsing elements as long as the parser returns `Just`.

many_ :: forall (m :: Type -> Type) o a. MonadThrow m => ConduitT Event o m (Maybe a) -> ConduitT Event o m () #

Like `many` but discards the results without building an intermediate list.

Since 1.5.0

manyIgnore :: forall (m :: Type -> Type) o a b. Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe b) -> ConduitT Event o m [a] #

Keep parsing elements as long as the parser returns `Just` or the ignore parser returns `Just`.

many' :: forall (m :: Type -> Type) o a. MonadThrow m => ConduitT Event o m (Maybe a) -> ConduitT Event o m [a] #

Like `many`, but any tags and content the consumer doesn't match on are silently ignored.

force #

Arguments

:: MonadThrow m |
=> String | Error message
-> m (Maybe a) | Optional parser to be forced
-> m a |

Force an optional parser into a required parser. All of the `tag` functions, `attr`, `choose` and `many` deal with `Maybe` parsers. Use this when you want to finally force something to happen.

# Streaming combinators

manyYield :: forall (m :: Type -> Type) a b. Monad m => ConduitT a b m (Maybe b) -> ConduitT a b m () #

Like `many`, but uses `yield` so the result list can be streamed to downstream conduits without waiting for `manyYield` to finish

manyYield' :: forall (m :: Type -> Type) b. MonadThrow m => ConduitT Event b m (Maybe b) -> ConduitT Event b m () #

Like `many'`, but uses `yield` so the result list can be streamed to downstream conduits without waiting for `manyYield'` to finish

manyIgnoreYield #

Arguments

:: forall (m :: Type -> Type) b. MonadThrow m |
=> ConduitT Event b m (Maybe b) | Consuming parser that generates the result stream
-> ConduitT Event b m (Maybe ()) | Ignore parser that consumes elements to be ignored
-> ConduitT Event b m () |

Like `manyIgnore`, but uses `yield` so the result list can be streamed to downstream conduits without waiting for `manyIgnoreYield` to finish

# Exceptions

data XmlException #

Constructors

XmlException |
Fields xmlErrorMessage :: String xmlBadInput :: Maybe Event
InvalidEndElement Name (Maybe Event) |
InvalidEntity String (Maybe Event) |
MissingAttribute String |
UnparsedAttributes [(Name, [Content])] |

#### Instances

Instances details

Exception XmlException # |
Instance details Defined in Text.XML.Stream.Parse Methods toException :: XmlException -> SomeException # fromException :: SomeException -> Maybe XmlException # displayException :: XmlException -> String # backtraceDesired :: XmlException -> Bool #
Show XmlException # |
Instance details Defined in Text.XML.Stream.Parse Methods showsPrec :: Int -> XmlException -> ShowS # show :: XmlException -> String # showList :: [XmlException] -> ShowS #

# Other types

data PositionRange #

#### Instances

Instances details

Show PositionRange |
Instance details Defined in Data.Conduit.Attoparsec Methods showsPrec :: Int -> PositionRange -> ShowS # show :: PositionRange -> String # showList :: [PositionRange] -> ShowS #
Eq PositionRange |
Instance details Defined in Data.Conduit.Attoparsec Methods (==) :: PositionRange -> PositionRange -> Bool # (/=) :: PositionRange -> PositionRange -> Bool #
Ord PositionRange |
Instance details Defined in Data.Conduit.Attoparsec Methods compare :: PositionRange -> PositionRange -> Ordering # (<) :: PositionRange -> PositionRange -> Bool # (<=) :: PositionRange -> PositionRange -> Bool # (>) :: PositionRange -> PositionRange -> Bool # (>=) :: PositionRange -> PositionRange -> Bool # max :: PositionRange -> PositionRange -> PositionRange # min :: PositionRange -> PositionRange -> PositionRange #

type EventPos = (Maybe PositionRange, Event) #