@@ -1,6 +1,6 @@
1{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE RecordWildCards #-}
3−-- | A module for first-approximation parsing of XML.
3+-- | A module for fast first-approximation parsing of XML.
4-- Note that entities, e.g. @&@, are not expanded.
4-- Note that entities, e.g. @&@, are not expanded.
5module Text.XML.Hexml(
5module Text.XML.Hexml(
6 Node, Attribute(..),
6 Node, Attribute(..),
@@ -58,15 +58,22 @@ foreign import ccall node_attributes :: Ptr CDocument -> Ptr CNode -> Ptr CInt -
58foreign import ccall node_childBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
58foreign import ccall node_childBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
59foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
59foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
61−-- | An XML document, created by 'documentParse'.
61+-- | A node in an XML document, created by 'documentParse', then calling functions such
62+-- as 'children' on that initial node.
62data Node = Node BS.ByteString (ForeignPtr CDocument) (Ptr CNode)
63data Node = Node BS.ByteString (ForeignPtr CDocument) (Ptr CNode)
65+-- | An XML attribute, comprising of a name and a value. As an example,
66+-- @hello=\"world\"@ would produce @Attribute \"hello\" \"world\"@.
64data Attribute = Attribute BS.ByteString BS.ByteString deriving (Show, Eq, Ord)
67data Attribute = Attribute BS.ByteString BS.ByteString deriving (Show, Eq, Ord)
66instance Show Node where
69instance Show Node where
67 show d = "Node " ++ show (BS.unpack $ outer d)
70 show d = "Node " ++ show (BS.unpack $ outer d)
73+-- | Parse a ByteString as an XML document, returning a 'Left' error message, or a 'Right' document.
74+-- Note that the returned node will have a 'name' of @\"\"@, no attributes, and content as per the document.
75+-- Often the first child will be the @<?xml ... ?>@ element. For documents which comprise a single
76+-- root element, use @'children' n !! 1@.
70parse :: BS.ByteString -> Either BS.ByteString Node
77parse :: BS.ByteString -> Either BS.ByteString Node
71parse src = unsafePerformIO $ BS.unsafeUseAsCStringLen (src <> BS.singleton '\0') $ \(str, len) -> do
78parse src = unsafePerformIO $ BS.unsafeUseAsCStringLen (src <> BS.singleton '\0') $ \(str, len) -> do
72 doc <- document_parse str (fromIntegral len - 1)
79 doc <- document_parse str (fromIntegral len - 1)
@@ -80,6 +87,8 @@ parse src = unsafePerformIO $ BS.unsafeUseAsCStringLen (src <> BS.singleton '\0'
80 doc <- newForeignPtr document_free_funptr doc
87 doc <- newForeignPtr document_free_funptr doc
81 return $ Right $ Node src doc node
88 return $ Right $ Node src doc node
90+-- | Given a node, rerender it to something with an equivalent parse tree.
91+-- Mostly useful for debugging - if you want the real source document use 'outer' instead.
83render :: Node -> BS.ByteString
92render :: Node -> BS.ByteString
84render (Node _ doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
93render (Node _ doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
85 i <- node_render d n nullPtr 0
94 i <- node_render d n nullPtr 0
@@ -100,15 +109,19 @@ attrPeek src doc a = unsafePerformIO $ withForeignPtr doc $ \_ -> do
100 val <- applyStr src <$> peekElemOff (castPtr a) 1
109 val <- applyStr src <$> peekElemOff (castPtr a) 1
101 return $ Attribute name val
110 return $ Attribute name val
112+-- | Get the name of a node, e.g. @<test />@ produces @\"test\"@.
103name :: Node -> BS.ByteString
113name :: Node -> BS.ByteString
104name = nodeBS 0
114name = nodeBS 0
116+-- | Get the inner text.
106inner :: Node -> BS.ByteString
117inner :: Node -> BS.ByteString
107inner = nodeBS 1
118inner = nodeBS 1
120+-- | Get the outer text.
109outer :: Node -> BS.ByteString
121outer :: Node -> BS.ByteString
110outer = nodeBS 2
122outer = nodeBS 2
124+-- | Get the contents of a node, the strings and child nodes.
112contents :: Node -> [Either BS.ByteString Node]
125contents :: Node -> [Either BS.ByteString Node]
113contents n@(Node src _ _) = f (strStart inner) outers
126contents n@(Node src _ _) = f (strStart inner) outers