我需要获取<p>
的第一个<div class="about">
的文本内容,编写以下代码:
tagTextS :: IOSArrow XmlTree String
tagTextS = getChildren >>> getText >>> arr stripString
parseDescription :: IOSArrow XmlTree String
parseDescription =
(
deep (isElem >>> hasName "div" >>> hasAttrValue "id" (== "company_about_full_description"))
>>> (arr (\x -> x) /> isElem >>> hasName "p") >. (!! 0) >>> tagTextS
) `orElse` (constA "")
看看这个arr (\x -> x)
- 没有它我无法达到结果。
parseDescription
?arr
之前和hasName "p"
之后使用括号? (一世
实际上找到了这个解决方案here)答案 0 :(得分:4)
import "hxt-xpath" Text.XML.HXT.XPath.Arrows (getXPathTrees)
...
xp = "//div[@class='about']/p[1]"
parseDescription = getXPathTrees xp >>> getChildren >>> getText
答案 1 :(得分:2)
另一个使用hxt核心的建议。
要强制执行第一个孩子,不能通过 getChildren 输出来完成,因为hxt箭头有一个特定的(&gt;&gt;&gt;),它将后续箭头映射到先前输出的每个列表项而不是输出列表,如haskellWiki hxt page中所述,虽然这是一个旧的定义,实际上它来自Category (.) composition。
getNthChild 可以从Control.Arrow.ArrowTree的getChildren攻击
import Data.Tree.Class (Tree)
import qualified Data.Tree.Class as T
-- if the nth element does not exist it will return an empty children list
getNthChild :: (ArrowList a, Tree t) => Int -> a (t b) (t b)
getNthChild n = arrL (take 1 . drop n . T.getChildren)
那么你的parseDescription就可以采用这种形式:
-- importing Text.XML.HXT.Arrow.XmlArrow (hasName, hasAttrValue)
parseDescription =
deep (isElem >>> hasName "div" >>> hasAttrValue "class" (== "about")
>>> getNthChild 0 >>> hasName "p"
)
>>> getChildren >>> getText
<强>更新即可。我找到了另一种使用changeChildren的方式:
getNthChild :: (ArrowTree a, Tree t) => Int -> a (t b) (t b)
getNthChild n = changeChildren (take 1 . drop n) >>> getChildren
更新:避免元素间距 - 节点过滤非元素子元素
import qualified Text.XML.HXT.DOM.XmlNode as XN
getNthChild :: (ArrowTree a, Tree t, XN.XmlNode b) => Int -> a (t b) (t b)
getNthChild n = changeChildren (take 1 . drop n . filter XN.isElem) >>> getChildren