@@ -1,11 +1,11 @@
1−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE RecordWildCards, BangPatterns #-}
22
33-- | A module for fast first-approximation parsing of XML.
44-- Note that entities, e.g. @&@, are not expanded.
55module Text.XML.Hexml(
66 Node, Attribute(..),
77 parse, render,
8− name, inner, outer,
8+ location, name, inner, outer,
99 attributes, children, contents,
1010 attributeBy, childrenBy
1111 ) where
@@ -179,3 +179,17 @@ attributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
179179 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
180180 r <- node_attributeBy d n bs $ fromIntegral len
181181 return $ if r == nullPtr then Nothing else Just $ attrPeek src doc r
182+
183+-- | Find the starting location of a node, the '<' character.
184+-- The first character will be reported as @(line 1,column 1)@, because thats
185+-- how error messages typically do it.
186+location :: Node -> (Int, Int)
187+location n@(Node src _ _) = BS.foldl' f (pair 1 1) $ BS.take (fromIntegral i) src
188+ where
189+ pair !a !b = (a,b)
190+
191+ i = strStart $ nodeStr 2 n
192+ f (!line, !col) c
193+ | c == '\n' = pair (line+1) 1
194+ | c == '\t' = pair line (col+8)
195+ | otherwise = pair line (col+1)