Question Thembelani Mlalazi · Jan 5, 2018

How to use %XML.Node

I have read here  and tried to use the supplied examples to see what they do but keep on getting error please advice:

Method GetXMLDocFromFile(file = "C:test2.xml") As %XML.Document
{
    set reader=##class(%XML.Reader).%New()
    set status=reader.OpenFile(file)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
    set document=reader.Document
    set reNo=##class(%XML.Node).%New()//check here
    set reNo.Document=document//check here
    do ..ShowNamespaces(document)
    do ..ShowNode(reNo)//check here
    quit document
}
Method ShowNamespaces(doc As %XML.Document)
{
    Set count=doc.CountNamespace()
    Write !, "Number of namespaces in document: "_count
    For i=1:1:count {
        Write !, "Namespace "_i_" is "_doc.GetNamespace(i)
}
}
//how to use the below method




Method ShowNode(node As %XML.Node)
{
    Write !,"LocalName="_node.LocalName
    If node.NodeType=$$$xmlELEMENTNODE  {
        Write !,"Namespace="_node.Namespace
    }
    If node.NodeType=$$$xmlELEMENTNODE {
        Write !,"NamespaceIndex="_node.NamespaceIndex
     }
    Write !,"Nil="_node.Nil
    Write !,"NodeData="_node.NodeData
    Write !,"NodeId="_node.NodeId
    Write !,"NodeType="_node.NodeType
    Write !,"QName="_node.QName
    Write !,"HasChildNodes returns "_node.HasChildNodes()
    Write !,"GetNumberAttributes returns "_node.GetNumberAttributes()
    Set status=node.GetText(.text)
    If status {
        Write !, "Text of the node is "_text
        } else {
            Write !, "GetText does not return text"
        }
}
  

the error I am getting is as follows:<UNDEFINED>zGetXMLDocFromFile+5^XMLToDyna.3 *reNo.If you check where I highlighted in red I have defined reNo so where am I going wrong

Comments

Eduard Lebedyuk · Jan 5, 2018

Use static classmethods, unless you need them to be instance methods.

0
Eduard Lebedyuk  Jan 6, 2018 to Robert Cemper

I'd move

Write !?(%lev*3)

into a separate method:

ClassMethod Log(text)
{
  Write !?(%lev*3), text
}
0
Eduard Lebedyuk · Jan 5, 2018

Try to remove reNo altogether and get the root node from the xml document:

do ..ShowNode(document.GetDocumentElement())

In GetDocumentElement method, you can see that for node to exist it needs 2 things:

  • Document
  • Pointer to the exact node

When you created the node manually,  you've done the first but not the second.

0
Robert Cemper  Jan 6, 2018 to Eduard Lebedyuk

This was more a code correction exercise. 
Honestly I wouldn't have done it that way at all. But using %XML.TextReader instead.
It was just to late in the evening to do a pretty solution.
The next auditor may do it.
 

BTW. for Attributes it'S %lev+1*3

0
Robert Cemper · Jan 5, 2018

As Eduard already pointed out there is just no need to use %XML.Node as %XML.Document inherits it already

I have elaborated your code also to cover Attributes and Chlidren in the document.
and added some readability features.

To some extend  %XML.TextReader could have done the same.

No need to copy the code from browser the class + test data is attached. xmlreading.zip  

Class XML.J [ Abstract ]
{
ClassMethod GetXMLDocFromFile(file = "C:\InterSystems\Cache\mgr\user\Test.xml") As %XML.Document
{
    set reader=##class(%XML.Reader).%New()
    set status=reader.OpenFile(file)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
#dim document as %XML.Document
    set document=reader.Document
 #; set reNo=##class(%XML.Node).%New() //check here
 #; set reNo.Document=document //check here
 #; do ..ShowNode(reNo)
    do ..ShowNamespaces(document)
#dim node as %XML.Node
    set %lev=0
    set node=document.GetDocumentElement()
    do ..Analyze(node)
    quit document
}
ClassMethod Analyze(node As %XML.Node)
{
    set hasChild =..ShowNode(node)
    set attribute=node.FirstAttributeName()
    while attribute'="" {
            do ..ShowAttribute(.attribute,node)
        }
    if hasChild {
        set tSC=node.MoveToFirstChild(1)
        if tSC , $i(%lev) {
            while tSC {
                do ..Analyze(node)
                set tSC=node.MoveToNextSibling(1)
                }
            do node.MoveToParent() if $i(%lev,-1)
            }
    }
    quit
}
ClassMethod ShowAttribute(ByRef attribute, node As %XML.Node)
{
   write !?(%lev+1*3),"Attribute_Name ",attribute
        ,!?(%lev+1*3),"Atribute_Value ",node.GetAttributeValue(attribute)
#; more to be added here
        ,!?(%lev+1*3),"--------------------------"
    set attribute=node.NextAttributeName(attribute)
    quit
}
ClassMethod ShowNamespaces(doc As %XML.Document)
{
    Set count=doc.CountNamespace()
    Write !, "Number of namespaces in document: "_count
    For i=1:1:count {
        Write !, "Namespace "_i_" is "_doc.GetNamespace(i)
}
}
// how to use the below method
ClassMethod ShowNode(node As %XML.Node) As %Boolean
{
    If node.NodeType=$$$xmlELEMENTNODE  {
        Write !?(%lev*3),"LocalName="_node.LocalName
#; Write !,"Namespace="_node.Namespace
#; }
#; If node.NodeType=$$$xmlELEMENTNODE {
#; Write !,"NamespaceIndex="_node.NamespaceIndex
        Write !?(%lev*3),"Nil="_node.Nil
        Write !?(%lev*3),"NodeData="_node.NodeData
        Write !?(%lev*3),"QName="_node.QName
    }
    Write !?(%lev*3),"NodeId="_node.NodeId
    Write !?(%lev*3),"NodeType="_node.NodeType
    Write !?(%lev*3),"HasChildNodes returns "_node.HasChildNodes()
    
    If node.NodeType=$$$xmlELEMENTNODE {
        Write !?(%lev*3),"GetNumberAttributes returns "_node.GetNumberAttributes()
        Set status=node.GetText(.text)
          If status {
           Write !?(%lev*3), "Text of the node is "_$tr(text,$c(10))
            else {
                Write !?(%lev*3), "GetText does not return text"
            }
    }
    quit node.HasChildNodes()
}
}
0