on master help sign in
Lots of documentation
7b6ff3dNeil Mitchell
src/Text/XML/Hexml.hs+23−7
@@ -58,8 +58,8 @@ 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)
60
60
61−-- | A node in an XML document, created by 'documentParse', then calling functions such
61+-- | A node in an XML document, created by 'parse', then calling functions such
62−-- as 'children' on that initial node.
62+-- as 'children' on that initial 'Node'.
63data Node = Node BS.ByteString (ForeignPtr CDocument) (Ptr CNode)
63data Node = Node BS.ByteString (ForeignPtr CDocument) (Ptr CNode)
64
64
65-- | An XML attribute, comprising of a name and a value. As an example,
65-- | An XML attribute, comprising of a name and a value. As an example,
@@ -72,7 +72,7 @@ instance Show Node where
72
72
73-- | Parse a ByteString as an XML document, returning a 'Left' error message, or a 'Right' document.
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.
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
75+-- Often the first child will be the @\<?xml ... ?\>@ element. For documents which comprise a single
76-- root element, use @'children' n !! 1@.
76-- root element, use @'children' n !! 1@.
77parse :: BS.ByteString -> Either BS.ByteString Node
77parse :: BS.ByteString -> Either BS.ByteString Node
78parse src = unsafePerformIO $ BS.unsafeUseAsCStringLen (src <> BS.singleton '\0') $ \(str, len) -> do
78parse src = unsafePerformIO $ BS.unsafeUseAsCStringLen (src <> BS.singleton '\0') $ \(str, len) -> do
@@ -109,19 +109,25 @@ attrPeek src doc a = unsafePerformIO $ withForeignPtr doc $ \_ -> do
109 val <- applyStr src <$> peekElemOff (castPtr a) 1
109 val <- applyStr src <$> peekElemOff (castPtr a) 1
110 return $ Attribute name val
110 return $ Attribute name val
111
111
112−-- | Get the name of a node, e.g. @<test />@ produces @\"test\"@.
112+-- | Get the name of a node, e.g. @\<test /\>@ produces @\"test\"@.
113name :: Node -> BS.ByteString
113name :: Node -> BS.ByteString
114name = nodeBS 0
114name = nodeBS 0
115
115
116−-- | Get the inner text.
116+-- | Get the inner text, from inside the tag, e.g. @\<test /\>@ produces @\"\"@
117+-- and @\<test\>hello\</test\>@ produces @\"hello\"@.
118+-- The result will have identical layout/spacing to the source document.
117inner :: Node -> BS.ByteString
119inner :: Node -> BS.ByteString
118inner = nodeBS 1
120inner = nodeBS 1
119
121
120−-- | Get the outer text.
122+-- | Get the outer text, including the tag itself, e.g. @\<test /\>@ produces @\"\<test /\>\"@
123+-- and @\<test\>hello\</test\>@ produces @\"\<test\>hello\</test\>\"@.
124+-- The result will have identical layout/spacing to the source document.
121outer :: Node -> BS.ByteString
125outer :: Node -> BS.ByteString
122outer = nodeBS 2
126outer = nodeBS 2
123
127
124−-- | Get the contents of a node, the strings and child nodes.
128+-- | Get the contents of a node, including both the content strings (as 'Left', never blank) and
129+-- the direct child nodes (as 'Right').
130+-- If you only want the child nodes, use 'children'.
125contents :: Node -> [Either BS.ByteString Node]
131contents :: Node -> [Either BS.ByteString Node]
126contents n@(Node src _ _) = f (strStart inner) outers
132contents n@(Node src _ _) = f (strStart inner) outers
127 where
133 where
@@ -133,6 +139,7 @@ contents n@(Node src _ _) = f (strStart inner) outers
133 inner = nodeStr 1 n
139 inner = nodeStr 1 n
134 outers = map (nodeStr 2 &&& id) $ children n
140 outers = map (nodeStr 2 &&& id) $ children n
135
141
142+-- | Get the direct child nodes of this node.
136children :: Node -> [Node]
143children :: Node -> [Node]
137children (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
144children (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
138 alloca $ \count -> do
145 alloca $ \count -> do
@@ -140,6 +147,7 @@ children (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
140 count <- fromIntegral <$> peek count
147 count <- fromIntegral <$> peek count
141 return [Node src doc $ plusPtr res $ i*szNode | i <- [0..count-1]]
148 return [Node src doc $ plusPtr res $ i*szNode | i <- [0..count-1]]
142
149
150+-- | Get the attributes of this node.
143attributes :: Node -> [Attribute]
151attributes :: Node -> [Attribute]
144attributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
152attributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
145 alloca $ \count -> do
153 alloca $ \count -> do
@@ -147,6 +155,10 @@ attributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
147 count <- fromIntegral <$> peek count
155 count <- fromIntegral <$> peek count
148 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
156 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
149
157
158+-- | Get the direct children of this node which have a specific name.
159+-- A more efficient version of:
160+--
161+-- > childrenBy p s = filter (\n -> name n == s) $ children p
150childrenBy :: Node -> BS.ByteString -> [Node]
162childrenBy :: Node -> BS.ByteString -> [Node]
151childrenBy (Node src doc n) str = go nullPtr
163childrenBy (Node src doc n) str = go nullPtr
152 where
164 where
@@ -155,6 +167,10 @@ childrenBy (Node src doc n) str = go nullPtr
155 r <- node_childBy d n old bs $ fromIntegral len
167 r <- node_childBy d n old bs $ fromIntegral len
156 return $ if r == nullPtr then [] else Node src doc r : go r
168 return $ if r == nullPtr then [] else Node src doc r : go r
157
169
170+-- | Get the first attribute of this node which has a specific name, if there is one.
171+-- A more efficient version of:
172+--
173+-- > attributeBy n s = listToMaybe $ filter (\(Attribute a _) -> a == s $ attributes n
158attributeBy :: Node -> BS.ByteString -> Maybe Attribute
174attributeBy :: Node -> BS.ByteString -> Maybe Attribute
159attributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
175attributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
160 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
176 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do