I want to use hxt-xslt
to transform a string containing a source xml based on a second string containing the xslt to a result xml string. So basically, I want a function of the type:
transf :: String -> String -> String
transf xmlStr xsltStr = ...
I searched around, there isn't an example for xslt in hxt
documentation, and the closest thing I can find is the code from this SO answer.
My problem is that the example and library uses IO
and arrows
heavily. I want to adapt the code and "strip" the IO
and arrow
to obtain a plain transform function that returns a String
or Maybe String
, but I don't know much about arrows.
I ask this because I need to parse HTMLs embedded in a CSV file. Having results in IO
and Arrows
makes it really difficult for the XSLT code to work with the rest of my code.
Based on @chi's comment on the origin version of the question, I looked into the documentation, and the closest thing I can get is the following code (by guessing and brute-forcing 3 out of the 4 functions in Text.XML.HXT.XSLT.{Compilation,Application}
):
{-# LANGUAGE Arrows, PackageImports #-}
import "hxt" Text.XML.HXT.Core
import "hxt-xslt" Text.XML.HXT.XSLT.Application
import "hxt-xslt" Text.XML.HXT.XSLT.Compilation
import "hxt-xslt" Text.XML.HXT.XSLT.Common
--strXml = "<?xml version='1.0' encoding='UTF-8'?>\n"
strXml = "<catalog>\n <cd>\n <title>Empire Burlesque</title>\n <artist>Bob Dylan</artist>\n <country>USA</country>\n <company>Columbia</company>\n <price>10.90</price>\n <year>1985</year>\n </cd>\n</catalog> "
--strXslt = "<?xml version='1.0'?>\n\n"
strXslt = "<xsl:stylesheet version='1.0'\nxmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n\n<xsl:template match='/'>\n <html>\n <body>\n <h2>My CD Collection</h2>\n <table border='1'>\n <tr bgcolor='#9acd32'>\n <th>Title</th>\n <th>Artist</th>\n </tr>\n <xsl:for-each select='catalog/cd'>\n <tr>\n <td><xsl:value-of select='title'/></td>\n <td><xsl:value-of select='artist'/></td>\n </tr>\n </xsl:for-each>\n </table>\n </body>\n </html>\n</xsl:template>\n\n</xsl:stylesheet> "
applyStylesheetStr strXslt strXml =
let
xml = head $ runLA xread strXml
xslt = assembleStylesheet (prepareXSLTDocument $head $ runLA xread strXslt) []
in
showTrees $ applyStylesheet xslt xml
The example XML and XSLT string came from a w3schools tutorial.
So far, the code is without IO, and arrows. And it outputs:
*Main> applyStylesheetStr strXslt strXml
"\n \n Empire Burlesque\n Bob Dylan\n USA\n Columbia\n 10.90\n 1985\n \n"
I have a few questions here:
I noticed that
xread
as used above cannot take standard XML headers like<?xml version='1.0' encoding='UTF-8'?>
. If included in the XML or XSLT, it returns an error. Is this expected or I am using it wrong?The correct output should be an HTML table as follows, when using IO/Arrows code from the SO answer:
<h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th>Title</th> <th>Artist</th> </tr> <tr> <td>Empire Burlesque</td> <td>Bob Dylan</td> </tr> </table>
How should I fix my code to get the pure XSLT transform?
Thanks.