-->

F# TypeProvider “XMLProvider” gives System.Excepti

2019-06-24 05:23发布

问题:

I'm trying to process Twitter tweets using the XML type provider as represented by the code below. The code works fine when accessing tweet data values using LINQ XElement functions, however it fails with an exception saying: “XML mismatch: Expected exactly one 'title' child”, when using the type created by the XMLProvider. I know namespaces are not given, however, I don't know how they would be specified with the provider, if they're needed.

// ...

open FSharp.Net
open FSharp.Data

let ns = "http://www.w3.org/2005/Atom"

// General helpers for XML

let xelem s (el: XContainer) = el.Element(XName.Get(s, ns)) 
// ...
let xvalue (el: XElement) = el.Value

let twitterUri = "http://search.twitter.com/search.atom?q=Windows8&rpp=100&lang=en"
type Tweets = XmlProvider<"SampleTweets.xml", Global=false>

let feed = Tweets.Load twitterUri

// title 0 & 1 produce correct values

let title0 = feed.XElement |> xelem "title" |> xvalue
let title1 = feed.XElement |> xelem "entry" |> xelem "title" |> xvalue

// title 2 produces: "XML mismatch: Expected exactly one 'title' child"

let title2 = feed.Title
let title3 = feed.GetEntries().[0].Title

回答1:

This was a bug in FSharp.Data related to the fact that there's a default namespace in the xml xmlns="http://www.w3.org/2005/Atom".

Version 1.1.3 fixed this, but you could also do the following as a workaround:

[<Literal>]
let twitterUri = "http://search.twitter.com/search.atom?q=Windows8&rpp=100&lang=en"
type Tweets = XmlProvider<twitterUri>

let feedXml = (Http.Request twitterUri).Replace("xmlns=\"http://www.w3.org/2005/Atom\"", null)

let feed = Tweets.Parse feedXml
let t = feed.Title