2008-12-02 50 views
20

mã C# này có lẽ không hiệu quả nhất nhưng nhận được những gì tôi muốn.F # Phân tích cú pháp XML

Làm cách nào để thực hiện điều tương tự trong mã F #?

string xml = " <EmailList> " + 
       "  <Email>[email protected]</Email> " + 
       "  <Email>[email protected]</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 ; 
     }    
    } 

Trả lời

47
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 

Nếu bạn thực sự muốn các ký tự dòng mới cuối cùng bạn có thể thêm nó vào bản đồ và String.Concat với chuỗi rỗng.

1

Nếu bạn nhìn vào mã của mình, bạn có một vài điều đang diễn ra. Đầu tiên là tải bộ sưu tập cho các nút Email, và thứ hai là thực sự làm một cái gì đó có ý nghĩa với họ.

Trước tiên, bạn muốn có chức năng trả lại bộ sưu tập. Một cái gì đó tương tự (và tôi đang trên máy Mac của tôi, vì vậy điều này có thể không hoạt động):


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(); 
     }    
    } 
} 

Bây giờ câu hỏi đặt ra xung quanh những gì bạn muốn làm gì với bộ sưu tập đó. Trong ví dụ trên, bạn đã ghép nối nó hoặc về cơ bản lưu trữ trạng thái.

Từ góc độ C#, bạn có thể bắt đầu sử dụng những thứ như câu trả lời từ this question (sử dụng LINQ) và this one.

Từ góc nhìn F #, giờ đây bạn có danh sách và chỉ có thể sử dụng các quy trình bình thường cho danh sách như this one hoặc here.

Bạn cũng có thể xem LINQ to XML (hoặc tại số 5 minute overview) để nhận thêm một số ý tưởng.

1

Làm thế nào về một cái gì đó dọc theo dòng:

#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 
+0

? Tôi không thể nhận được các dòng IEnumerable để biên dịch. Bạn lấy loại này từ đâu? – JaredPar

+0

Có lý do cụ thể nào để sử dụng IEnumerable.iter thay vì Seq.iter không? Không có sự khác biệt giữa hai, Seq là thành ngữ F #. – Juliet

+0

Không, ngoài tôi đã không lập trình F # trong một vài năm. :-) –

6

Đây là mã tương tự để làm điều này trong F #. Tôi chắc rằng một trong những ninja của F # sẽ đưa ra một phiên bản tốt hơn ở đây sau một phút nữa.

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() 
Các vấn đề liên quan