git.iko.soy/typeable/pandoc
on master help sign in
Docx Reader: preprocess Document body to unwrap "w:sdt" elements

We walk through the document (using the zipper in Text.XML.Light.Cursor) to unwrap the sdt tags before doing the rest of the parsing of the document. Note that the function is generically named `walkDocument` in case we need to do any further preprocessing in the future. Closes #4190

commitdc3ee500a0447dc258ae5b49cf5907cba0d407aa authorJesse Rosenthal <jrosenthal@jhu.edu> dateWed 27 Dec 2017, 09:49 (9 years ago) parent7e8cfc0
1 file changed+31−1
src/Text/Pandoc/Readers/Docx/Parse.hs+31−1
src/Text/Pandoc/Readers/Docx/Parse.hs+31−1
@@ -73,6 +73,7 @@ import Text.TeXMath (Exp)
7373import Text.TeXMath.Readers.OMML (readOMML)
7474import Text.TeXMath.Unicode.Fonts (Font (..), getUnicode, stringToFont)
7575import Text.XML.Light
76+import qualified Text.XML.Light.Cursor as XMLC
7677
7778data ReaderEnv = ReaderEnv { envNotes :: Notes
7879 , envComments :: Comments
@@ -117,6 +118,32 @@ mapD f xs =
117118 in
118119 concatMapM handler xs
119120
121+unwrapSDT :: NameSpaces -> Content -> Content
122+unwrapSDT ns (Elem element)
123+ | isElem ns "w" "sdt" element
124+ , Just sdtContent <- findChildByName ns "w" "sdtContent" element
125+ , child : _ <- elChildren sdtContent
126+ = Elem child
127+unwrapSDT _ content = content
128+
129+walkDocument' :: NameSpaces -> XMLC.Cursor -> XMLC.Cursor
130+walkDocument' ns cur =
131+ let modifiedCur = XMLC.modifyContent (unwrapSDT ns) cur
132+ in
133+ case XMLC.nextDF modifiedCur of
134+ Just cur' -> walkDocument' ns cur'
135+ Nothing -> XMLC.root modifiedCur
136+
137+walkDocument :: NameSpaces -> Element -> Maybe Element
138+walkDocument ns element =
139+ let cur = XMLC.fromContent (Elem element)
140+ cur' = walkDocument' ns cur
141+ in
142+ case XMLC.toTree cur' of
143+ Elem element' -> Just element'
144+ _ -> Nothing
145+
146+
120147data Docx = Docx Document
121148 deriving Show
122149
@@ -298,7 +325,10 @@ archiveToDocument zf = do
298325 docElem <- maybeToD $ (parseXMLDoc . UTF8.toStringLazy . fromEntry) entry
299326 let namespaces = elemToNameSpaces docElem
300327 bodyElem <- maybeToD $ findChildByName namespaces "w" "body" docElem
301− body <- elemToBody namespaces bodyElem
328+ let bodyElem' = case walkDocument namespaces bodyElem of
329+ Just e -> e
330+ Nothing -> bodyElem
331+ body <- elemToBody namespaces bodyElem'
302332 return $ Document namespaces body
303333
304334elemToBody :: NameSpaces -> Element -> D Body