Replacement for MoveXMLNode()

Share your advanced PureBasic knowledge/code with the community.
StanDan
User
User
Posts: 57
Joined: Sun Feb 26, 2006 3:43 am
Location: Missouri, United States

Replacement for MoveXMLNode()

Post by StanDan »

I was having trouble getting MoveXMLNode() to work (bug report here.) I did a search on the forum and found out that MoveXMLNode() had never been mentioned anywhere. So obviously it's not a wildly popular feature. :D

Anyway, here's my solution, in case anybody uses it and runs into the same problem I had.

It's not a perfect solutions since GetXMLNodeText() returns all the text within the given node, without regard to its position in relation to child nodes (i.e. in moving <p>This<b>will</b>not<b>work</b></p> to another location you will get <p><b>will</b><b>work</b>Thisnot</p>.) There's no easy way to get around this without resorting to the expat API, which is beyond me.

It's great for configuration files though, where you just need to maintain the DOM structure and nodes which contain data have only one child (the actual text.)

Code: Select all

Prototype.l ProtoMvXMLNode(*node, *par, *prv=0)
Prototype.l ProtoCpXMLNode(*node, *par, *prv=0)

Procedure.l XMLDeepCopy(*node, *dest)
  If *node = 0 Or *dest = 0
    ProcedureReturn 0
  EndIf
  nodeType = XMLNodeType(*node)
  If nodeType = #PB_XML_Normal Or nodeType = #PB_XML_Instruction
    nodeName.s = GetXMLNodeName(*node)
    If nodeType = #PB_XML_Instruction And nodeName <> ""
      SetXMLNodeName(*dest, nodeName)
    Else
      SetXMLNodeName(*dest, nodeName)
    EndIf
  EndIf
  If nodeType <> #PB_XML_Root
    nodeText.s = GetXMLNodeText(*node)
    SetXMLNodeText(*dest, nodeText)
  EndIf
  If nodeType = #PB_XML_Normal And ExamineXMLAttributes(*node)
    Repeat
      hasAttr = NextXMLAttribute(*node)
      If hasAttr <> 0
        attr.s = XMLAttributeName(*node)
        value.s = XMLAttributeValue(*node)
        SetXMLAttribute(*dest, attr, value)
      EndIf
    Until hasAttr = 0
  EndIf
  *child = ChildXMLNode(*node)
  If *child = 0
    ProcedureReturn 1
  EndIf
  
  NewList Nodes.l()

  ; Otherwise add the next children.
  Repeat
    AddElement(Nodes())
    Nodes() = *child
    *child = NextXMLNode(*child)
  Until *child = 0
  
  *new = 0
  *par = *dest
  *prv = 0
  ForEach Nodes()
    nodeType = XMLNodeType(Nodes())
    If nodeType = #PB_XML_Root
      ProcedureReturn 0
    EndIf
    If *prv = 0
      *new = CreateXMLNode(*par, 0, nodeType)
      If *new = 0
        ProcedureReturn 0
      EndIf
    Else
      *new = CreateXMLNode(*par, *prv, nodeType)
      If *new = 0
        ProcedureReturn 0
      EndIf
    EndIf
    If XMLDeepCopy(Nodes(), *new) = 0
      ProcedureReturn 0
    EndIf
    *prv = *new
  Next
  ProcedureReturn 1
EndProcedure

Procedure.l ProcCpXMLNode(*node, *par, *prv)
  If *par = 0 Or *node = 0
    ProcedureReturn 0
  EndIf
  *new = 0
  nodeType = XMLNodeType(*node)
  If nodeType = #PB_XML_Root
    ProcedureReturn 0
  EndIf
  If *prv = 0
    *new = CreateXMLNode(*par, 0, nodeType)
    If *new = 0
      ProcedureReturn 0
    EndIf
  Else
    *new = CreateXMLNode(*par, *prv, nodeType)
    If *new = 0
      ProcedureReturn 0
    EndIf
  EndIf
  ProcedureReturn XMLDeepCopy(*node, *new)
EndProcedure

Procedure.l ProcMvXMLNode(*node, *par, *prv)
  ret.l = ProcCpXMLNode(*node, *par, *prv)
  If ret > 0
    DeleteXMLNode(*node)
  EndIf
  ProcedureReturn ret
EndProcedure

CpXMLNode.ProtoCpXMLNode = @ProcCpXMLNode()
MvXMLNode.ProtoMvXMLNode = @ProcMvXMLNode()
afriend
User
User
Posts: 20
Joined: Thu Aug 09, 2007 5:47 am
Location: Melbourne, Australia

xml move

Post by afriend »

Thanks fo posting. It appears your program cleans up a bit.
Post Reply