Извлечение значений из поддерева

Я анализирую файл 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)
Другие вопросы по тегам