F# - Recursive Read XML Data
Deat alls,
I try to work this few rows of code, but I really do not know why the 'myTreeNodes' List of TreeNodes reset during the call of the 'extractData' routine.
It seem that I have respected all the necessary constraints and good practice, but something ... I have missed!
Many thanks in advance for any of your suggestion
ANN
Code
let GetFactors =
let errorHeader = "Gasket Factor - List Retrieve"
let doc = new XmlDocument()
let myTreeNodes = List<TreeNode>.Empty
let readData (xmlNode:XmlNode) (treeNodes:List<TreeNode>) =
match xmlNode.Name with
| "GasketFactors" ->
let attribs = xmlNode.Attributes
if (attribs.Count > 0) then
let name = GetStringData "Version" attribs
printfn "GASKET FACTORS VERSION: '%s'" name
| "Gasket" ->
let attribs = xmlNode.Attributes
if (attribs.Count > 0) then
let name = GetStringData "Type" attribs
let mainNode = new TreeNode(name)
let treeNodes = mainNode :: treeNodes
printfn " - Type: %s " name
| "Data" ->
let attribs = xmlNode.Attributes
if (attribs.Count > 0) then
let parent = List.head treeNodes
let gskType = parent.Name
let gskSource = GetStringData "Source" attribs
let gskSubType = GetStringData "SubType" attribs
let gskMaterialGroup = GetStringData "Group" attribs
let gskMaterial = GetStringData "Material" attribs
let gskMaterialFiller = GetStringData "Filler" attribs
let gskMaterialLayers = GetStringData "Layers" attribs
let gsk_m =
let value = GetStringData "m" attribs
0.0
let gsk_y =
let value = GetStringData "y" attribs
0.0
let gskFactors = new Factors(gsk_m, gsk_y)
let gskService = GetStringData "Service" attribs
let gskUserNote = GetStringData "Note" attribs
let gskShow = GetBoolData "Show" attribs
let newGasket = new Gasket(gskSource, gskType, gskSubType,
gskMaterial, gskMaterialGroup, gskMaterialFiller, gskMaterialLayers,
gskFactors, new Geometry(),
gskService, gskUserNote, gskShow)
let childNode = new TreeNode(gskSubType)
childNode.Tag <- newGasket
parent.Nodes.Add(childNode) |> ignore
printfn " - Sub Type: %s " (newGasket.ToString())
| _ ->
printfn "%A" xmlNode
let rec extractData (xmlNode:XmlNode) (treeNodes:List<TreeNode>) =
if (xmlNode <> null) then
match xmlNode.NodeType with
| XmlNodeType.Element ->
readData xmlNode treeNodes
printfn "{TEXT: %s}" xmlNode.Value
if (xmlNode.HasChildNodes) then
extractData xmlNode.FirstChild treeNodes
else
let next = xmlNode.NextSibling
let parent = xmlNode.ParentNode
if (next <> null) then
extractData next treeNodes
else
extractData parent treeNodes
| XmlNodeType.Text | XmlNodeType.CDATA ->
printfn "{TEXT: %s}" xmlNode.Value
extractData xmlNode.NextSibling treeNodes
| XmlNodeType.Comment ->
printfn "{COMMENT: %s}" xmlNode.Value
extractData xmlNode.NextSibling treeNodes
| XmlNodeType.ProcessingInstruction | XmlNodeType.XmlDeclaration ->
printfn "{DECLARATION: %s = %s}" xmlNode.Name xmlNode.Value
extractData xmlNode.NextSibling treeNodes
| _ ->
printfn "{OTHER: %s = %s}" xmlNode.Name xmlNode.Value
extractData xmlNode.NextSibling treeNodes
else
()
try
doc.Load( Resources.GasketXMLFactorsPath )
with
| ex -> failwith (errorHeader + ": Not Possible to Load!" + ex.ToString())
开发者_如何学运维 extractData doc.FirstChild myTreeNodes
myTreeNodes
XML Source
{GasketFactors Version="1.0.0.0"} {Gasket Type="Self-Energizing"} {Data Source="ASME" SubType="Welded" m="0.00" y="0.0 psi" /} {Data Source="ASME" SubType="Any" m="0.00" y="0.0 psi" /} {/Gasket} {Gasket Type="Vegetable Fibers"} {Data Source="ASME" SubType="Any" Material="Any" m="1.75" y="1100.0 psi" /} {/Gasket} {/GasketFactors}
I haven't dived deeply, but if
let myTreeNodes = List<TreeNode>.Empty
is F# list<'T>, then it is immutable and when you append element to list - you construct new list instead of mutating source one. You can either on every step take source list and return modified version or use mutable collection like System.Collections.Generic.List<'T> or System.Collections.Generic.LinkedList<'T> to accumulate changes.
精彩评论