The node.
method was added to the node API in Iguana 5.6.1. It allows you to directly set the value of a node without needing to reference it from it’s parent node.setNodeValue()
So what does this mean, and when do we need to use it? Well that is actually two questions, so lets answer them separately.
What does this mean and how does it work?
Let’s say we want to set the Time value in an HL7 ADT message:
Before 5.6.1 the only way to set the value for a node was to reference it from it’s parent node MSH[7]:
From 5.6.1 on you can also use the node.
method:setNodeValue()
This just looks like a more complicated way to do same thing… so where is the added value?
Well, the advantage is that it still works when you cannot access the parent node:
So this was an an artificial example just to demonstrate how it works, next we will explain when it is actually needed.
When do we need to use setNodeValue, when is it useful?
One of our users identified that it was not possible to directly change the value of a node. He came across this when he created a node.clearNode()
function, and he was not able to clear the value for a leaf node passed to the function. See the original discussion on LinkedIn.
The requirements for node:clearNode()
are very simple:
- For a non-leaf node remove all the child nodes
- For a leaf node remove the data (by setting it to an empty string)
The issue is with second requirement, as the only way to set a leaf node was from its parent. So lets demonstrate the problem and the solution.
Issue: Cannot clear a leaf node
This is the original function:
As you can see it works when called with a non-leaf node:
However it fails when called using a leaf node:
Solution: Clear leaf nodes using setNodeValue()
The solution is to add a condition to use setNodeValue()
to clear leaf nodes.
Here is the updated function:
As you can see it now works correctly with leaf nodes:
Code for you to try
function main(Data) local Msg = hl7.message{vmd='demo.vmd', name='ADT'} -- assign the parent node to a variable for demonstration purposes local ParentNode = Msg.MSH[7] trace(ParentNode) -- set the Time field by referencing it from the parent node ParentNode[1] = os.date() -- default auto-completion syntax ParentNode.Time = os.date() -- alternative syntax same result trace(ParentNode) -- NOTE: normally we would use this syntax - "ParentNode" was just for emphasis! Msg.MSH[7][1] = os.date() -- set the Time field using setNodeValue() ParentNode[1]:setNodeValue(os.date()) -- default syntax ParentNode.Time:setNodeValue(os.date()) -- alternative syntax trace(ParentNode) -- NOTE: as before we would use this syntax - rather than "ParentNode" Msg.MSH[7][1]:setNodeValue(os.date()) -- assign the Time node (reference) to a variable local Time = Msg.MSH[7][1] -- set the Time node (reference) using setNodeValue() Time:setNodeValue(os.date()) trace(Time) -- assigning the date directly just overwrites the node (reference) Time = os.date() trace(Time) -- NOTE: The date we previously assigned to the Time node is unaffected trace(Msg.MSH[7][1]) -- clearing a non-leaf node works correctly trace(Msg.MSH) --Msg.MSH:clearNode() -- commented out so code below works trace(Msg.MSH) -- assign the Time leaf node to a variable local Time = Msg.MSH[7][1] -- attempting to clear the leaf node fails -- clearing the leaf node now succeeds - using clearNode_new() trace(Msg.MSH[7]) Time:clearNode() trace(Msg.MSH[7]) end -- original function - does not work on leaf nodes function node:clearNode() for nChild = self:childCount(), 1 , -1 do self:remove(nChild) end end -- updated function works on leaf nodes function node:clearNode_new() if self:isLeaf() then self:setNodeValue('') else for nChild = self:childCount(), 1 , -1 do self:remove(nChild) end end end -- you could also create a (recursive) function to empty all the nodes -- NOTE: this is a lot slower than clearNode() function node:emptyNode() if self:isLeaf() then self:setNodeValue('') else for nChild = self:childCount(), 1 , -1 do self[nChild]:emptyNode() end end end