Parsing Function for XML data

1,261 views
Skip to first unread message

Jim Kirkby

unread,
Mar 21, 2016, 12:20:27 PM3/21/16
to Node-RED
I seem to have come to a rookie error junction.

I can make requests and post various bits of data using HTTP requests etc. However I'm working with the IoBridge API and I'm trying to parse a request so I can pull various elements out of the an XML return. I can get what I want working by being very explicit in my API request but I thought I could make a full request and then parse it using a function to then send what I want to another server.

I've drawn a blank, This is what I get back which is great. What I want to do is pull out say the status and just send that off to another server. I've tried using tmeplates which are returning nothing. I'm making some sort of school boy error here. How would you guys parse this data out?

<?xml version="1.0" encoding="utf-8"?>
        <module>
            <serial>xxxxxxxxx</serial>
            <label>Boiler Monitor</label>
            <lat>00</lat>
            <long>00</long>
            <location>London</location>
            <time_zone>Europe/London</time_zone>
            <local_time>2016-03-21 16:10:18</local_time>
            <datetime>2016-03-21 16:10:18</datetime>
            <status>Online</status>

    <channel_1>
        <label>Under Floor Out</label>
        <AnalogInput>35.4</AnalogInput>
        <AnalogInputRaw>623</AnalogInputRaw>
        <AnalogInputScale>Temp C</AnalogInputScale>
        <DigitalInput>On</DigitalInput>
        <DigitalInputState>1</DigitalInputState>
        <PulseCountRaw>2</PulseCountRaw>
        <DigitalOutput>Off</DigitalOutput>
        <DigitalOutputState>0</DigitalOutputState>
        <Variable1>0</Variable1>
    </channel_1>
    <channel_2>
        <label>Under Floor Return</label>
        <AnalogInput>20.4</AnalogInput>
        <AnalogInputRaw>460</AnalogInputRaw>
        <AnalogInputScale>Temp C</AnalogInputScale>
        <DigitalInput>On</DigitalInput>
        <DigitalInputState>1</DigitalInputState>
        <PulseCountRaw>1</PulseCountRaw>
        <DigitalOutput>Off</DigitalOutput>
        <DigitalOutputState>0</DigitalOutputState>
        <Variable1>0</Variable1>
    </channel_2>
    <channel_3>
        <label>Hot Water</label>
        <AnalogInput>29.7</AnalogInput>
        <AnalogInputRaw>563</AnalogInputRaw>
        <AnalogInputScale>Temp C</AnalogInputScale>
        <DigitalInput>On</DigitalInput>
        <DigitalInputState>1</DigitalInputState>
        <PulseCountRaw>2</PulseCountRaw>
        <DigitalOutput>Off</DigitalOutput>
        <DigitalOutputState>0</DigitalOutputState>
        <Variable1>0</Variable1>
    </channel_3>
    <channel_4>
        <label>LCD Output</label>
        <AnalogInput>302</AnalogInput>
        <AnalogInputRaw>302</AnalogInputRaw>
        <AnalogInputScale>Raw</AnalogInputScale>
        <DigitalInput>On</DigitalInput>
        <DigitalInputState>1</DigitalInputState>
        <PulseCountRaw>2</PulseCountRaw>
        <DigitalOutput>Off</DigitalOutput>
        <DigitalOutputState>0</DigitalOutputState>
        <Variable1>0</Variable1>
    </channel_4>

        </module>

Any clues deeply appreciated.

Jim

Nicholas O'Leary

unread,
Mar 21, 2016, 12:29:18 PM3/21/16
to Node-RED Mailing List
Have a look at the XML node in the palette - that will help convert this XML blob in to a JavaScript object you can start pulling apart in a Function node.

Nick



--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+u...@googlegroups.com.
To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
For more options, visit https://groups.google.com/d/optout.

Dave C-J

unread,
Mar 21, 2016, 4:12:44 PM3/21/16
to node...@googlegroups.com
maybe something like

[{"id":"4bd6bb1a.0ffb84","type":"xml","z":"4affede3.af6f44","name":"","attr":"","chr":"","x":505.5,"y":1679,"wires":[["580f06c.09603f8"]]},{"id":"580f06c.09603f8","type":"function","z":"4affede3.af6f44","name":"","func":"msg.payload = msg.payload.module.status[0];\nreturn msg;","outputs":1,"noerr":0,"x":655.5,"y":1720,"wires":[["6e4bf0de.249f9"]]}]

Jim Kirkby

unread,
Mar 22, 2016, 8:13:50 AM3/22/16
to Node-RED
That works!! I've been trying to get this working for days now so thank you.

As an extra question if I want to go further down into the data i.e. Channel_1 do I just need to extend the statement?

Jim

Dave C-J

unread,
Mar 22, 2016, 8:46:18 AM3/22/16
to node...@googlegroups.com
yes - being careful to note that some parts are arrays [ ] and some just objects { }
so you need to index / select appropriately.

Jim Kirkby

unread,
Apr 2, 2016, 11:43:59 AM4/2/16
to Node-RED
Thanks to everyones help I've made progress.

I'm still struggling with the arrays [ ] and objects { } bit of this.

I've got this coming in as a get from Metoffice

<SiteRep>
<Wx>
<Param name="Gunits="mph">Wind Gust</Param>
<Param name="Tunits="C">Temperature</Param>
<Param name="Vunits="m">Visibility</Param>
<Param name="Dunits="compass">Wind Direction</Param>
<Param name="Sunits="mph">Wind Speed</Param>
<Param name="Wunits="">Weather Type</Param>
<Param name="Punits="hpa">Pressure</Param>
<Param name="Ptunits="Pa/s">Pressure Tendency</Param>
<Param name="Dpunits="C">Dew Point</Param>
<Param name="Hunits="%">Screen Relative Humidity</Param>
</Wx>
<DV dataDate="2016-04-02T11:00:00Ztype="Obs">
<Location i="3772lat="51.479lon="-0.4491name="HEATHROWcountry="ENGLANDcontinent="EUROPEelevation="25.0">
<Period type="Dayvalue="2016-04-01Z">
<Rep D="SH="62.6P="1020S="14T="11.6V="22000W="1Pt="FDp="4.8">660</Rep>
<Rep D="SH="58.4P="1019S="15T="12.1V="30000W="3Pt="FDp="4.3">720</Rep>
<Rep D="SH="53.0P="1019S="16T="12.4V="40000W="3Pt="FDp="3.2">780</Rep>
<Rep D="SH="57.6P="1018S="16T="12.0V="29000W="3Pt="FDp="4.0">840</Rep>
<Rep D="SH="58.1P="1018S="16T="12.1V="35000W="3Pt="FDp="4.2">900</Rep>
<Rep D="SH="57.2P="1017S="16T="11.9V="35000W="7Pt="FDp="3.8">960</Rep>
<Rep D="SH="46.5P="1017S="16T="11.2V="45000W="1Pt="FDp="0.3">1020</Rep>
<Rep D="SH="51.0P="1017S="14T="10.7V="45000W="7Pt="FDp="1.1">1080</Rep>
<Rep D="SH="55.8P="1017S="13T="9.9V="35000W="8Pt="FDp="1.6">1140</Rep>
<Rep D="SH="60.8P="1017S="11T="9.5V="40000W="8Pt="SDp="2.4">1200</Rep>
<Rep D="SSEH="71.6P="1017S="10T="9.0V="35000W="8Pt="FDp="4.2">1260</Rep>
<Rep D="SEH="77.8P="1016S="7T="8.4V="19000W="8Pt="FDp="4.8">1320</Rep>
<Rep D="SSEH="77.8P="1016S="7T="8.2V="18000W="8Pt="FDp="4.6">1380</Rep>
</Period>
<Period type="Dayvalue="2016-04-02Z">...</Period>
</Location>
</DV>
</SiteRep>

I put it through the XML node and I can parse various bits out. i.e I can split out the Wx data and the DV data in a function node and send the messages to different paths.

var WX = msg.payload.SiteRep.Wx[0]
var DV = msg.payload.SiteRep.DV[0]
//msg.payload = msg.payload.SiteRep.DV[0];

var msg1 = { payload:(WX) };
var msg2 = { payload:(DV) };

return [[msg1],[msg2] ];

I can also split out the Location bit using another function

var Location = msg.payload.Location[0]


var msg1 = { payload:(Location) };
var msg2 = { payload:("Data from Msg2") };

return [[msg1],[msg2]];

Works perfectly. 

I'm just struggling to pull out the location data. If I use the following function node I just get the first Letter of each variable i.e. msg.payload.$.name[0] returns just the H for Heathrow

var Name = msg.payload.$.name[0]
var Country = msg.payload.$.country[0]
//var DV = msg.payload.SiteRep.DV[0]
//msg.payload = msg.payload.SiteRep.DV[0];

var msg1 = { payload:(Name) };
var msg2 = { payload:(Country) };

return [[msg1],[msg2]];

I genuinely can't make out what I'm doing wrong. I had it working on all the IoBridge stuff just not for this.

Mark Setrem

unread,
Apr 2, 2016, 12:17:03 PM4/2/16
to Node-RED


msg.payload = msg.payload.SiteRep.DV[0].Location[0].$.name;

should give you HEATHROW

Jim Kirkby

unread,
Apr 2, 2016, 12:47:28 PM4/2/16
to Node-RED
Yes, I think I had just worked it out, the [0] is all about the array.....

I made it work by error, forgetting to put the [0] in a function and it popped out Heathrow just before you're mail

The world is my Lobster now.

Cheers chap
Reply all
Reply to author
Forward
0 new messages