开发者

F# - Recursive Read XML Data

开发者 https://www.devze.com 2023-01-12 09:53 出处:网络
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.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消