¿Cómo acceder al atributo de un nodo principal utilizando el proveedor de tipos XML de F# Data?
-
21-12-2019 - |
Pregunta
Cómo acceder al atributo de un nodo padre usando Proveedor de tipos XML de datos de F#?Digamos que tengo el siguiente XML:
<?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>
Y quiero usarlo en el siguiente código:
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
*OBSERVACIÓN:L1.x obviamente no funcionará, pero quiero lograr algo similar.
Solución
Creo que la forma más sencilla sería utilizar Seq.tryPick
sobre el L1
s, con la función interna buscando entre los hijos del actual 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow