Извлечение значений из поддерева
Я анализирую файл XML с HXT
и я пытаюсь разбить некоторые извлечения узлов на модульные части (я использовал это в качестве руководства). К сожалению, я не могу понять, как применить некоторые селекторы, когда я делаю разбор первого уровня.
import Text.XML.HXT.Core
let node tag = multi (hasName tag)
xml <- readFile "test.xml"
let doc = readString [withValidate yes, withParseHTML no, withWarnings no] xml
books <- runX $ doc >>> node "book"
Я вижу, что у книг есть тип [XmlTree]
:t books
books :: [XmlTree]
Теперь я хотел бы получить первый элемент books
а затем извлечь некоторые значения внутри поддерева.
let b = head(books)
runX $ b >>> node "cost"
Couldn't match type ‘Data.Tree.NTree.TypeDefs.NTree’
with ‘IOSLA (XIOState ()) XmlTree’
Expected type: IOSLA (XIOState ()) XmlTree XNode
Actual type: XmlTree
In the first argument of ‘(>>>)’, namely ‘b’
In the second argument of ‘($)’, namely ‘b >>> node "cost"’
Я не могу найти селекторы, когда у меня есть XmlTree
и я показываю вышеупомянутое неправильное использование, чтобы проиллюстрировать то, что я хотел бы. Я знаю, что я могу сделать это:
runX $ doc >>> node "book" >>> node "cost" /> getText
["55.9","95.0"]
Но меня интересует не только cost
но и много других элементов внутри book
, Файл XML довольно глубокий, поэтому я не хочу вкладывать все в <+>
и многие предпочитают извлекать нужный мне кусок, а затем извлекать подэлементы в отдельной функции.
Пример (готовый) XML-файл:
<?xml version="1.0" encoding="UTF-8"?><start xmlns="http://www.example.com/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<books>
<book>
<author>
<name>
<first>Joe</first>
<last>Smith</last>
</name>
<city>New York City</city>
</author>
<released>1990-11-15</released>
<isbn>1234567890</isbn>
<publisher>X Publisher</publisher>
<cost>55.9</cost>
</book>
<book>
<author>
<name>
<first>Jane</first>
<last>Jones</last>
</name>
<city>San Francisco</city>
</author>
<released>1999-01-19</released>
<isbn>0987654321</isbn>
<publisher>Y Publisher</publisher>
<cost>95.0</cost>
</book>
</books>
</start>
Может кто-нибудь помочь мне понять, как извлечь подэлементы book
? В идеале с чем-то хорошим >>>
а также node
так что я могу определить свои собственные функции, такие как getCost
, getName
и т. д. что каждый будет примерно иметь подпись XmlTree -> [String]
1 ответ
doc
это не то, что вы думали. Имеет тип IOStateArrow s b XmlTree
, Вы действительно должны прочитать ваше руководство еще раз, все, что вы хотели знать, было заключено под заголовком "Избегание ввода-вывода".
Стрелки в основном функции. SomeArrow a b
может рассматриваться как обобщенная / специализированная функция типа a -> b
, >>>
и другие операторы в области видимости предназначены для композиции стрелок, аналогично композиции функций. Ваш books
имеет тип [XmlTree]
так что это не стрелка и не может быть составлена из стрелок. Что отвечает вашим потребностям runLA
, это превращает стрелу как node "tag"
к нормальной функции:
module Main where
import Text.XML.HXT.Core
main = do
html <- readFile "test.xml"
let doc = readString [withValidate yes, withParseHTML no, withWarnings no] html
books <- runX $ doc >>> node "book"
-- runLA (node "cost" /> getText) :: XmlTree -> [String]
let costs = books >>= runLA (node "cost" /> getText)
print costs
node tag = multi (hasName tag)