Разбор F # XML - PullRequest
       22

Разбор F # XML

21 голосов
/ 02 декабря 2008

этот код на c #, вероятно, не самый эффективный, но он добивается того, чего я хочу.

Как мне сделать то же самое в коде F #?

    string xml = " <EmailList> " +
               "      <Email>test@email.com</Email> " +
               "      <Email>test2@email.com</Email> " +
               " </EmailList> ";

    XmlDocument xdoc = new XmlDocument();
    XmlNodeList nodeList;
    String emailList = string.Empty;
    xdoc.LoadXml(xml);
    nodeList = xdoc.SelectNodes("//EmailList");
    foreach (XmlNode item in nodeList)
    {
        foreach (XmlNode email in item)
        {
             emailList +=  email.InnerText.ToString() +  Environment.NewLine ;
        }               
    }

Ответы [ 5 ]

48 голосов
/ 02 декабря 2008
let doc = new XmlDocument() in
    doc.LoadXml xml;
    doc.SelectNodes "/EmailList/Email/text()"
        |> Seq.cast<XmlNode>
        |> Seq.map (fun node -> node.Value)
        |> String.concat Environment.NewLine

Если вам действительно нужен последний завершающий символ новой строки, вы можете добавить его на карту и String.concat с пустой строкой.

7 голосов
/ 24 ноября 2015

То же самое с провайдером XML-данных F # :

type EmailList = XmlProvider<"""<EmailList><Email>email</Email><Email>email</Email></EmailList>""">
let data = EmailList.Parse("""
    <EmailList>
        <Email>test@email.com</Email>
        <Email>test2@email.com</Email>
    </EmailList>
    """)

let emailList = data.Emails |> String.concat Environment.NewLine
6 голосов
/ 02 декабря 2008

Вот аналогичный код для этого в F #. Я уверен, что один из F # ниндзя выложит лучшую версию здесь через минуту.

open System.Xml

let getList x = 
    let getDoc =
        let doc = new XmlDocument()
        doc.LoadXml(x) |> ignore
        doc
    let getEmail (n:XmlNode) = n.InnerText.ToString() 
    let doc = getDoc
    let build = new System.Text.StringBuilder()
    doc.SelectNodes("//EmailList") 
        |> Seq.cast<XmlNode>
        |> Seq.map (fun n -> n.ChildNodes )
        |> Seq.map_concat (Seq.cast<XmlNode>)
        |> Seq.map(fun (n:XmlNode) -> getEmail n) 
        |> Seq.iter (fun e -> build.AppendLine(e) |> ignore )
    build.ToString()
1 голос
/ 02 декабря 2008

Как насчет чего-то вроде:

#light
open System.Xml

let xml = "..."

let emailList = 
    let xdoc = new XmlDocument()
    xdoc.LoadXml(xml)

    let mutable list = []
    let addEmail e = list <- e :: emailList

    xdoc.SelectNodes("//EmailList")
    |> IEnumerable.iter(fun(item:XmlNode) ->
        item
        |> IEnumerable.iter(fun(e:XmlNode) ->
            addEmail e.InnerText; ()))

    list
1 голос
/ 02 декабря 2008

Если вы посмотрите на свой код, у вас есть пара вещей. Первый загружает коллекцию для узлов электронной почты, а второй фактически делает с ними что-то значимое.

Во-первых, вы хотите, чтобы ваша функция возвращала коллекцию. Что-то вроде (и я на моем Mac, так что это может не работать):


List<string> EmailAddresses(string xml)
{
    XmlDocument xdoc = new XmlDocument();
    XmlNodeList nodeList;
    String emailList = string.Empty;
    xdoc.LoadXml(xml);
    nodeList = xdoc.SelectNodes("//EmailList");
    foreach (XmlNode item in nodeList)
    {
        foreach (XmlNode email in item)
        {
             yield email.InnerText.ToString();
        }               
    }
}

Теперь возникает вопрос, что вы хотите делать с этой коллекцией. В приведенном выше примере вы объединяли его или в основном хранили состояние.

С точки зрения C # вы можете начать использовать такие вещи, как ответы из этого вопроса (с использованием LINQ) и этого .

С точки зрения F # у вас теперь есть список, и вы можете просто использовать обычные процедуры для списка, такие как этот или здесь .

Вы также можете посмотреть LINQ to XML (или 5-минутный обзор ), чтобы получить больше идей.

...