我希望将所有title
元素替换为h1
,h2
,...,h6
元素,具体取决于祖先的数量section
元素。输入/输出示例:
Input.xml文件
<document>
<section>
<title>Title A</title>
<section>
<title>Title B</title>
</section>
<section>
<title>Title C</title>
<section>
<title>Title D</title>
</section>
</section>
</section>
</document>
的Output.xml
<document>
<section>
<h1>Title A</h1>
<section>
<h2>Title B</h2>
</section>
<section>
<h2>Title C</h2>
<section>
<h3>Title D</h3>
</section>
</section>
</section>
</document>
我可以使用类似
的title
替换所有h1
s
swapTitles :: ArrowXml a => a XmlTree XmlTree
swapTitles = processTopDown $
(changeQName . const $ mkName "h1")
`when`
(isElem >>> (hasQName $ mkName "title"))
我相信我应该使用ArrowState,但我无法弄清楚如何。有人能指出我正确的方向吗?
答案 0 :(得分:0)
将XSL与包hxt-xslt一起使用。标准使生活更轻松: - )
{-# LANGUAGE Arrows, PackageImports #-}
import System.Environment ( getArgs )
import System.Exit (exitSuccess, exitWith, ExitCode(..))
import Control.Arrow
import "hxt" Text.XML.HXT.Core
import "hxt" Text.XML.HXT.DOM.XmlKeywords
import "hxt-xslt" Text.XML.HXT.XSLT.XsltArrows
import "hxt" Text.XML.HXT.Arrow.XmlState.TraceHandling (withTraceLevel)
process :: String -> String -> IO [String]
process xslStylesheetPath xmlDocPath = do
-- compile stylesheet
compiledStyleSheetResults <- runX $
arr (const xslStylesheetPath)
>>> readXSLTDoc [ withValidate yes, withInputEncoding utf8] -- withTrace 2
>>> {- withTraceLevel 2 -} xsltCompileStylesheet
case compiledStyleSheetResults of
[] -> return ["error compiling " ++ xslStylesheetPath]
compiledStyleSheet : _ -> do
-- apply compiled stylesheet to xml doc
runX $ arr (const xmlDocPath)
>>> readXSLTDoc [ withValidate yes, withInputEncoding utf8] -- withTrace 2
>>> xsltApplyStylesheet compiledStyleSheet
>>> writeDocumentToString [withOutputEncoding utf8,
withXmlPi yes, withIndent yes]
-- readXSLTDoc from internals of module Text.XML.HXT.XSLT.XsltArrows
readXSLTDoc :: SysConfigList -> IOSArrow String XmlTree
readXSLTDoc options
= readFromDocument (options ++ defaultOptions)
where
defaultOptions
= [ withCheckNamespaces yes
, withValidate no
, withPreserveComment no
]
main = do
args <- getArgs
case args of
[arg1, arg2] -> do
results <- process arg1 arg2
case results of
[] -> putStrLn "errors"
result : _ -> putStrLn result
exitSuccess
_ -> do
putStrLn "missing parameters: xslStylesheetPath xmlDocPath"
exitWith $ ExitFailure 1
使用XSL文件&#34; mystyle.xsl&#34;
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="document">
<xsl:copy>
<xsl:call-template name="myloop">
<xsl:with-param name="nesting" select="0"/>
</xsl:call-template>
</xsl:copy>
</xsl:for-each>
</xsl:template>
<xsl:template name="myloop">
<xsl:param name="nesting"/>
<xsl:if test="title">
<xsl:element name="{concat('h',string($nesting))}">
<xsl:value-of select="title" />
</xsl:element>
</xsl:if>
<xsl:for-each select="section">
<xsl:copy>
<xsl:call-template name="myloop">
<xsl:with-param name="nesting" select="$nesting+1"/>
</xsl:call-template>
</xsl:copy>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
使用&#34; yourdata.xml&#34;
<?xml version="1.0" encoding="UTF-8"?>
<document>
<section>
<title>Title A</title>
<section>
<title>Title B</title>
</section>
<section>
<title>Title C</title>
<section>
<title>Title D</title>
</section>
</section>
</section>
</document>
运行
runhaskell test.hs mystyle.xsl yourdata.xml
结果:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<section>
<h1>Title A</h1>
<section>
<h2>Title B</h2>
</section>
<section>
<h2>Title C</h2>
<section>
<h3>Title D</h3>
</section>
</section>
</section>
</document>