2014-02-25 17 views
2

如何使用F# Data's XML Type Provider来访问父节点的属性?比方说,我有以下XML:如何使用F#Data的XML Type Provider访问父节点的属性?

<?xml version="1.0" encoding="UTF-16"?> 
<ROOT> 
    <level1 name="level1Name1" x="8"> 
     <level2 name="level2Name1" a="8" b="104" /> 
     <level2 name="level2Name2" a="85" b="140" /> 
    </level1> 
    <level1 name="level1Name2" x="10"> 
     <level2 name="level2Name3" a="50" b="500" /> 
     <level2 name="level2Name4" a="376" b="1065" /> 
     <level2 name="level2Name5" a="10" b="100" /> 
     <level2 name="level2Name6" a="700" b="700" /> 
    </level1> 
    <level1 name="level1Name3" x="7"> 
     <level2 name="level2Name7" a="502" b="66" /> 
    </level1> 
</ROOT> 

而且我想在下面的代码使用它:

open System 
open System.Xml.Linq 
open FSharp.Data 

type myXmlType = XmlProvider<"""<?xml version="1.0" encoding="UTF-16"?><ROOT><level1 name="level1Name1" x="8"><level2 name="level2Name1" a="8" b="104" /><level2 name="level2Name2" a="85" b="140" /></level1><level1 name="level1Name2" x="10"><level2 name="level2Name3" a="50" b="500" /><level2 name="level2Name4" a="376" b="1065" /><level2 name="level2Name5" a="10" b="100" /><level2 name="level2Name6" a="700" b="700" /></level1><level1 name="level1Name3" x="7"><level2 name="level2Name7" a="502" b="66" /></level1></ROOT>"""> 

let myXml = myXmlType.Parse("""<?xml version="1.0" encoding="UTF-16"?><ROOT><level1 name="level1Name1" x="8"><level2 name="level2Name1" a="8" b="104" /><level2 name="level2Name2" a="85" b="140" /></level1><level1 name="level1Name2" x="10"><level2 name="level2Name3" a="50" b="500" /><level2 name="level2Name4" a="376" b="1065" /><level2 name="level2Name5" a="10" b="100" /><level2 name="level2Name6" a="700" b="700" /></level1><level1 name="level1Name3" x="7"><level2 name="level2Name7" a="502" b="66" /></level1></ROOT>""") 

let howToDoIt = 
    myXml.GetLevel1s() 
    |> Seq.collect (fun L1 -> L1.GetLevel2s()) 
    |> Seq.tryFind (fun L2 -> L2.b = L1.x * L2.a) // *REMARK 
    |> function 
    | None -> "" 
    | Some L2 -> L2.Name 

* REMARK:L1.x显然是行不通的,但我想实现类似的东西。

回答

4

我认为最简单的办法是在L1的使用Seq.tryPick,与内部功能当前L1的儿童中搜索:

myXml.GetLevel1s() 
|> Seq.tryPick (fun L1 -> 
    L1.GetLevel2s() 
    |> Seq.tryFind (fun L2 -> L2.b = L1.x * L2.a)) 
|> function 
| None -> "" 
| Some L2 -> L2.Name 
+1

+1作为一个方面说明,我可能会取代最后三行使用临时变量'optName',然后使用'defaultArg'函数。 –

+0

我们可以一直深入到一个层次,直到达到F#Limbo。 – prokilomer

相关问题