2015-01-14 17 views
0

循環是否有可能通過以下文件循環使用F#秩序,僞代碼真是假:)通過他們的訂單多/不同的XML元素與F#數據

<root> 
    <element_a>1</element_a> 
    <element_b>2</element_b> 
    <element_c>3</element_c> 
    <element_a>4</element_a> 
</root> 

僞代碼:

root.? |> Array.iter (fun e -> 
    printfn "%s:%s" e.DisplayName e.Value 
) 

結果:

element_a:1 
element_b:2 
element_c:3 
element_a:4 

所以,

  1. 我可以通過原始順序中的不同元素循環?
  2. 如果是,我怎麼知道它是哪個元素?

回答

1

XML類型提供程序不會爲您提供任何類型的方法。這就是說,使得有可能訪問所有的孩子,作爲一些提供的類型的集合將是一個有用的擴展!

但是,您可以使用底層的XElement表示形式來遍歷所有子級,然後將其重新轉換爲由XML類型提供程序生成的靜態類型化表示形式。

使用你的基本例子,所有元素的類型被推斷爲int,所以這並不是所有的有趣的事情(沒有孩子......),但是說你有這樣的東西,其中不同的元素都有相同的子元素a與屬性n

type Demo = XmlProvider<"""<root> 
    <element_a><a n="foo" /></element_a> 
    <element_b><a n="bar" /></element_b> 
    <element_c><a n="zoo" /></element_c> 
    <element_a><a n="goo" /></element_a> 
</root>"""> 

現在可以使用root.XElement.Descendants()得到一個類型化方式的元素:

let root = Demo.GetSample() 
for child in root.XElement.Descendants() do 
    let asA = new Demo.ElementA(child) 
    printfn "%A" asA.A.N 

一旦我們有了孩子元素,我們將其重新包裝成靜態類型的表示形式。在這裏,我們總是使用爲<element_a>生成的類型(這可能是錯誤的 - 如果其他元素有不同的結構,但它在這裏很好地工作)。

+0

感謝你的答案,我希望我不必使用XElement,但它的工作! 我不知道新的Demo.ElementA(孩子),所以使我的代碼更好。 – AndrewBay

0

可以biuld一​​個XDocument和通過根的孩子迭代:

#r "System.XML.Linq" 
open System.IO; 
open System.Xml.Linq; 

let xml = @" 
      <root> 
       <element_a>1</element_a> 
       <element_b>2</element_b> 
       <element_c>3</element_c> 
       <element_a>4</element_a> 
      </root>" 
let xdoc = XDocument.Load(new StringReader(xml)) 
let rootEl = xdoc.Elements() |> Seq.head 
rootEl.Elements() |> Seq.iter (fun el -> printfn "%s: %s" el.Name.LocalName el.Value) 

應該產生所期望的輸出。

如果要同名元件之間進行區分,則可以互換Seq.iterSeq.iteri,即傳遞順序索引到所提供的功能:

rootEl.Elements() |> Seq.iteri (fun idx el -> printfn "Idx %d: %s: %s" idx el.Name.LocalName el.Value) 

生產:

Idx 0: element_a: 1 
Idx 1: element_b: 2 
Idx 2: element_c: 3 
Idx 3: element_a: 4 
相關問題