::xox
Class XmlNodeWriter

Heritage:
::xotcl::Object
Direct Known Subclasses:
::xox::SimpleXmlNodeWriter,

Associated Test:
::xox::test::TestXmlNodeWriter

Class XmlNodeWriter
superclass ::xotcl::Object,
Library of methods to write XML from a tree of ::xox::Nodes.

 The primary methods in this library are writeXmlFile and generateXml.
Variables
NameDefault ValueClassComment
dom    ::xox::XmlNodeWriter
 The DOM object that is currently being created by generateXml
externalRootNodes    ::xox::XmlNodeWriter
 Other root nodes that may be found during root node check when writing XML.
rootNode    ::xox::XmlNodeWriter
 The root ::xox::Node that is being written to XML
 
Methods
NameComment
assertCorrectPath {item}   Asserts that item has a valid root node that is either rootNode or one of the externalRootNodes
buildArrayVariable {parentDomNode node variable}   Creates the DOM nodes needed to represent an array variable on an ::xox::Node
buildArrayVariableXml {parentDomNode variable value index {indexType ""} {valueType ""}}   Arguments: parentDomNode - the DOM node to create the new DOM nodes under
buildMixinXml {parentDomNode mixin}   Creates an DOM node that has the type="mixin" to denote that the value of the DOM node is a mixin
buildNodeXml {parentDomNode node}   Builds the xml for a node
buildVariable {parentDomNode node variable}   Creates the DOM nodes needed to represent the variable and values of a variable on a ::xox:Node
buildVariableXml {parentDomNode variable value {valueType ""}}   Creates a new DOM node as a child of parentDomNode that represents the variable and value of a variable on a ::xox::Node
buildXml {parentDomNode node}   Recursive call that builds the XML from a subtree of ::xox::Nodes
checkIsNotNode {item}   Checks if item is not a Node
fail {message}   Simple implementation of the fail method
generateXml {node}   Generates XML from a tree of ::xox::Nodes
writeXmlFile {node fileName}   Writes an XML representation of a tree of ::xox::Nodes to a file named fileName
   
Methods from ::xotcl::Object
#, ., ?, ?code, ?methods, ?object, abstract, copy, coverageFilter, defaultmethod, extractConfigureArg, filterappend, garbageCollect, get#, getClean#, hasclass, init, methodTag, mixinappend, move, profileFilter, self, setParameterDefaults, shell, tclcmd, traceFilter,
 
Instproc Detail

assertCorrectPath

Description:
 Asserts that item has a valid root node that is either
 rootNode or one of the externalRootNodes.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc assertCorrectPath {item}  {
   

        my instvar rootNode externalRootNodes

        set root [ $item findRoot ]

        if { "$root" == "$rootNode" } { return }

        if [ my exists externalRootNodes ] {
        foreach externalRootNode $externalRootNodes {

            if { "$root" == "$externalRootNode" } { return }
        }
        }

        my debug "Warning: [ $item path ] $item has incorrect root: [ $root getNodeName ]\n Expected $rootNode [ $rootNode info class ]\n Actual: $root [ $root info class ]"
    
}

buildArrayVariable

Description:
 Creates the DOM nodes needed to represent an array variable on an ::xox::Node.

 Arguments:

 parentDomNodea - the DOM node to create the new DOM nodes under.
 node - The ::xox::Node that holds the variable, variable.
 variable - The name of the variable to convert to XML DOM.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildArrayVariable {parentDomNode node variable}  {
   

       if { "nameToNodes" == "$variable" } { return }

       foreach name [ $node array names $variable ] {

           set indexType ""

           if [ Object isobject $name ] {
               set indexType path
           }

           set value [ $node set ${variable}($name) ]

           if { "" == "$value" } { 
               
               my buildArrayVariableXml $parentDomNode ${variable} $value $name $indexType
               continue 
           }

           if [ Object isclass [ lindex $value 0 ] ] {

               my buildArrayVariableXml $parentDomNode ${variable} $value $name $indexType

           } elseif [ Object isobject [ lindex $value 0 ] ] {
               if {  [ llength $value ] != 1 } {

                   set paths ""

                   foreach item $value {

                       if [ my checkIsNotNode $item ] { continue }
                       my assertCorrectPath $item

                       lappend paths [ $item path ]
                   }
                   my buildArrayVariableXml $parentDomNode ${variable} $paths $name $indexType paths
                   
               } else {

                   if [ my checkIsNotNode $value ] { continue }
                   my assertCorrectPath $value

                   my buildArrayVariableXml $parentDomNode ${variable} [ $value path ] $name $indexType path
               }
           } else {

               my buildArrayVariableXml $parentDomNode ${variable} $value $name $indexType
           }
       }
   
}

buildArrayVariableXml

Description:
 Arguments:

 parentDomNode - the DOM node to create the new DOM nodes under.
 variable - The name of the variable to convert to XML DOM.
 value - The value of the variable.
 index - The key of the value in the array.
 indexType - The type of value in the index node.
 valueType - The type of value in the value node.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildArrayVariableXml {parentDomNode variable value index {indexType ""} {valueType ""}}  {
   

       my instvar dom

       set variableNode [ $dom createElement $variable  ]
       set valueText [ $dom createCDATASection $value ]

       $variableNode setAttribute type array

       if { "$indexType" == "" } {

           set indexNode [ $dom createElement index  ]
           set indexText [ $dom createCDATASection $index ]

       } elseif { "$indexType" == "path" } {

           set indexNode [ $dom createElement index  ]
           set indexText [ $dom createCDATASection [ $index path ] ]

           $indexNode setAttribute type $indexType
       } else {

           my fail "[ self class ][ self proc ] indexType $indexType not implemented"

       }
       
       set valueNode [ $dom createElement value  ]
       set valueText [ $dom createCDATASection $value ]


       if { "$valueType" != "" } {
           $valueNode setAttribute type $valueType
       }

       $variableNode appendChild $indexNode
       $variableNode appendChild $valueNode

       $indexNode appendChild $indexText
       $valueNode appendChild $valueText

       $parentDomNode appendChild $variableNode
   
}

buildMixinXml

Description:
 Creates an DOM node that has the type="mixin" to denote that
 the value of the DOM node is a mixin.  

 Arguments:
 
 parentDomNode - The parent DOM node to create the new DOM node under.
 mixin - The Class to specify as a mixin in the value of the new DOM node.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildMixinXml {parentDomNode mixin}  {
   

       my instvar dom

       set mixinNode [ $dom createElement mixin  ]
       set mixinText [ $dom createCDATASection $mixin ]
       $mixinNode setAttribute type mixin

       $mixinNode appendChild $mixinText
       $parentDomNode appendChild $mixinNode
   
}

buildNodeXml

Description:
 Builds the xml for a node.  This creates a new DOM node
 with the name of the class of the ::xox::Node and appends
 that as a child of parentDomNode.

 Arguments:

 parentDomNode - the parent of the new DOM node. 
 node - the ::xox::Node instance to build XML for.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildNodeXml {parentDomNode node}  {
   

        my instvar dom

           set tdomNode [ $dom createElement [ $node info class ]  ]
           $parentDomNode appendChild $tdomNode
           my buildXml $tdomNode $node 
    
}

buildVariable

Description:
 Creates the DOM nodes needed to represent the variable and values
 of a variable on a ::xox:Node.

 Arguments:

 parentDomNode - The parent DOM node to create the new DOM nodes under.
 node - A reference to the ::xox::Node that has the variable, variable.
 variable - The variable name.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildVariable {parentDomNode node variable}  {
   

       my instvar dom

       set value [ $node set $variable ]

       regsub -all {&} $value { } value

       if { "" == "$value" } {

           my buildVariableXml $parentDomNode ${variable} $value
           return 
       }
       catch {
           set object ""
           set object [ lindex $value 0 ]
       }
       if [ uplevel #0 [ list ::xotcl::Object isclass $object ] ] {

         my buildVariableXml $parentDomNode ${variable} $value
           
       } elseif [ uplevel #0 [ list ::xotcl::Object isobject $object ] ] {
           if {  [ llength $value ] > 1 } {

               set paths ""

               foreach item $value {

                   if [ my checkIsNotNode $item ] { continue }
                   lappend paths [ $item path ]
                   my assertCorrectPath $item
               }

               my buildVariableXml $parentDomNode ${variable} $paths paths

           } else {
               if [ my checkIsNotNode $value ] { return }
               my assertCorrectPath $value

               my buildVariableXml $parentDomNode ${variable} [ $value path ] path
           }
       } else {
           my buildVariableXml $parentDomNode ${variable} $value 
       }
   
}

buildVariableXml

Description:
 Creates a new DOM node as a child of parentDomNode that represents
 the variable and value of a variable on a ::xox::Node.

 Creates a new DOM node with the name of the name of the variable.  The text
 value of the DOM node is the value of the variable.

 Optionally the variable DOM node may have a valueType. This may be the value: path or paths.
 Path and paths valueTypes are used to denote that the value is a path to an object in
 the ::xox::Node tree.

 Arguments:

 parentDomNode - the DOM node to create the new DOM nodes under.
 variable - The name of the variable to convert to XML DOM.
 value - The value of the variable.
 valueType - The type of value in the value node.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildVariableXml {parentDomNode variable value {valueType ""}}  {
   

       my instvar dom

       set variableNode [ $dom createElement $variable  ]
       set valueText [ $dom createCDATASection $value ]

       if { "$valueType" != "" } {
           $variableNode setAttribute type $valueType
       }

       $variableNode appendChild $valueText
       $parentDomNode appendChild $variableNode
   
}

buildXml

Description:
 Recursive call that builds the XML from a subtree of ::xox::Nodes.

 buildXml creates DOM nodes that represent all the variables, array
 variables, mixins, and child nodes for this subtree starting with node.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc buildXml {parentDomNode node}  {
   

       my instvar dom

       my buildVariableXml $parentDomNode nodeName [ $node getNodeName ]

       foreach mixin [ lsort [ $node info mixin ] ] {

           my buildMixinXml $parentDomNode $mixin
       }

       foreach var [ lsort [ $node info vars ] ] {

           if { "$var" == "nodeName" } { continue }
           if { "$var" == "parentNode" } { continue }
           if { "$var" == "__autonames" } { continue }

           if [ $node array exists $var ] {

               my buildArrayVariable $parentDomNode $node $var

           } else {

               my buildVariable $parentDomNode $node $var
          }
       }

       foreach subElement [ $node nodes ] {

           if [ $subElement hasclass ::xox::Node ] {

               my buildNodeXml $parentDomNode $subElement
           }
       }
    
}

checkIsNotNode

Description:
 Checks if item is not a Node. 

 Returns:

 1 - if item is not a Node.
 0 - if item is a Node instance.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc checkIsNotNode {item}  {
   

        if { ! [ Object isobject $item ] } { return 1 }

        if { [ $item hasclass ::xotcl::Class ] } {

            return 1
        }

        if { ! [ $item hasclass ::xox::Node ] } {

           puts "Warning: $item is a [ $item info class ]"
           return 1
        }
        return 0
    
}

fail

Description:
 Simple implementation of the fail method.  This just
 calls the global error method with the message.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc fail {message}  {
   

        uplevel #0 [ list error $message ]
    
}

generateXml

Description:
 Generates XML from a tree of ::xox::Nodes.

 Arguments:

 node - The root of a tree of ::xox::Nodes.

 Returns:
 
 The xml generated.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc generateXml {node}  {
   

       my instvar rootNode dom

       set rootNode $node

       set dom [ dom createDocument [ $node info class ] ]
       set root [ $dom documentElement ]

       global env

       set comment [ $dom createComment "Generated by [ my info class ] $env(USER) at [ clock format [ clock seconds ] ]" ]
       my buildXml $root $node

       return "[ $comment asXML ]\n[ $root asXML ]"
   
}

writeXmlFile

Description:
 Writes an XML representation of a tree of ::xox::Nodes to a file
 named fileName.

 Returns: 

 The xml written to the file.
Arguments:
Code:
  ::xox::XmlNodeWriter instproc writeXmlFile {node fileName}  {
   

       set file [ open $fileName w ]
       set xml  [ my generateXml $node ]
       puts $file $xml
       flush $file
       close $file

       return $xml
   
}