OPSL
OPSL

Reputation: 131

XPath not returning Node Value ASP.NET 4.5

Having a small issue here, I am working on converting a legacy Classic ASP application to ASP.NET 4.5 for a customer and have the need to pull data from an XML file but I cannot get the value of a single node, my code just returns nothing.

XML file

<?xml version="1.0" encoding="UTF-8"?>
<Devices-Detail-Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.embeddeddatasystems.com/schema/owserver">
<PollCount>150722</PollCount>
<DevicesConnected>4</DevicesConnected>
<LoopTime>3.974</LoopTime>
<DataErrors>2</DataErrors>
<DeviceName>OW_SERVER-Enet</DeviceName>
<HostName>EDSOWSERVER</HostName
<MACAddress>00:50:C2:91:B3:9C</MACAddress>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>2D0000023C519A28</ROMId>
<Health>7</Health>
<RawData>0E014B467FFF021000000</RawData>
<PrimaryValue>16.8750 Deg C</PrimaryValue>
<Temperature Units="Centigrade">16.8750</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>0</PowerSource>
</owd_DS18B20>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>DA000002E0E5A928</ROMId>
<Health>7</Health>
<RawData>32014B467FFF0E101E000000</RawData>
<PrimaryValue>19.1250 Deg C</PrimaryValue>
<Temperature Units="Centigrade">19.1250</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>0</PowerSource>
</owd_DS18B20>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>C3000002E0EE1B28</ROMId>
<Health>7</Health>
<RawData>1D014B467FFF0310C5000000</RawData>
<PrimaryValue>17.8125 Deg C</PrimaryValue>
<Temperature Units="Centigrade">17.8125</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>0</PowerSource>
</owd_DS18B20>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>070000023DBB7F28</ROMId>
<Health>7</Health>
<RawData>52014B467FFF0E10FFFF0000000000000000</RawData>
<PrimaryValue>21.1250 Deg C</PrimaryValue>
<Temperature Units="Centigrade">21.1250</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>255</PowerSource>
</owd_DS18B20>
</Devices-Detail-Response>

I need to be able to get the Temperature value based on the ROMId as there can be upto 22 sensors connected at any one time.

I have tried the following but it always yeilds nothing:

Imports System.Xml
Dim m_xmld As XmlDocument
Dim m_nodelist As XmlNodeList
Dim m_node As XmlNode
Dim Temperature As String = String.Empty

m_xmld = New XmlDocument()
m_xmld.Load("http://" & server_ip & "/details.xml")
Dim m_xmlns As New XmlNamespaceManager(m_xmld.NameTable)
m_xmlns.AddNamespace("opsm_ns", "http://tempuri.org/zitem.xsd")

For Each node As XmlNode In
m_xmld.SelectNodes("//opsm_ns:owd_DS18B20[ROMId='" & deviceId & "']",m_xmlns)
Console.WriteLine(node.Attributes("Temperature").Value)
Next

The document loads but I simply cannot get the data out as nothing is returned, what am I missing here??

Thanks in advance

Ozzie

UPDATE 2: Have grabbed the full XML output in Visual Studio and updated above

UPDATE 3: Have used the example from @CrnaStena below with the above XML and still does not return any value

Upvotes: 2

Views: 179

Answers (2)

CrnaStena
CrnaStena

Reputation: 3157

So here is my LinqPad example in C#, sorry I have not used VB in 20 years. I've expanded your XML to add additional node which has different ROMid and temperature.

void Main()
{
        // XML to load
    var xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<Devices-Detail-Response>
    <PollCount>36593</PollCount>
    <DevicesConnected>2</DevicesConnected>
    <LoopTime>1.031</LoopTime>
    <DataErrors>0</DataErrors>
    <DeviceName>OW_SERVER-Enet</DeviceName>
    <HostName>EDSOWSERVER</HostName>
    <MACAddress>00:50:C2:91:B3:9C</MACAddress>
    <owd_DS18B20 Description=""Programmable resolution thermometer"">
        <Name>DS18B20</Name>
        <Family>28</Family>
        <ROMId>2D0000023C519A28</ROMId>
        <Health>7</Health>
        <RawData>61014B467FFF0F1002FF</RawData>
        <PrimaryValue>22.0625 Deg C</PrimaryValue>
        <Temperature Units=""Centigrade"">22.0625</Temperature>
        <UserByte1 Writable=""True"">75</UserByte1>
        <UserByte2 Writable=""True"">70</UserByte2>
        <Resolution>12</Resolution>
        <PowerSource>255</PowerSource>
    </owd_DS18B20>
    <owd_DS18B20 Description=""Programmable resolution thermometer"">
        <Name>DS18B20</Name>
        <Family>28</Family>
        <ROMId>2D0000023C519A29</ROMId>
        <Health>7</Health>
        <RawData>61014B467FFF0F1002FF</RawData>
        <PrimaryValue>22.0625 Deg C</PrimaryValue>
        <Temperature Units=""Centigrade"">24.0625</Temperature>
        <UserByte1 Writable=""True"">75</UserByte1>
        <UserByte2 Writable=""True"">70</UserByte2>
        <Resolution>12</Resolution>
        <PowerSource>255</PowerSource>
    </owd_DS18B20>  
</Devices-Detail-Response>";

    var xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xml);

    var nodes = xmlDoc.SelectNodes("//owd_DS18B20/ROMId[text()='2D0000023C519A28']/../Temperature");
    foreach(XmlNode node in nodes)
    {
        node.InnerText.Dump();
    }


}

And result shows 22.0625

Update 1

And I brushed up on VB and here is LinqPad VB code with same result:

Sub Main
    Dim xml As String
    Dim m_xmld As XmlDocument

    xml = <![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Devices-Detail-Response>
    <PollCount>36593</PollCount>
    <DevicesConnected>2</DevicesConnected>
    <LoopTime>1.031</LoopTime>
    <DataErrors>0</DataErrors>
    <DeviceName>OW_SERVER-Enet</DeviceName>
    <HostName>EDSOWSERVER</HostName>
    <MACAddress>00:50:C2:91:B3:9C</MACAddress>
    <owd_DS18B20 Description="Programmable resolution thermometer">
        <Name>DS18B20</Name>
        <Family>28</Family>
        <ROMId>2D0000023C519A28</ROMId>
        <Health>7</Health>
        <RawData>61014B467FFF0F1002FF</RawData>
        <PrimaryValue>22.0625 Deg C</PrimaryValue>
        <Temperature Units="Centigrade">22.0625</Temperature>
        <UserByte1 Writable="True">75</UserByte1>
        <UserByte2 Writable="True">70</UserByte2>
        <Resolution>12</Resolution>
        <PowerSource>255</PowerSource>
    </owd_DS18B20>
    <owd_DS18B20 Description="Programmable resolution thermometer">
        <Name>DS18B20</Name>
        <Family>28</Family>
        <ROMId>2D0000023C519A29</ROMId>
        <Health>7</Health>
        <RawData>61014B467FFF0F1002FF</RawData>
        <PrimaryValue>22.0625 Deg C</PrimaryValue>
        <Temperature Units="Centigrade">24.0625</Temperature>
        <UserByte1 Writable="True">75</UserByte1>
        <UserByte2 Writable="True">70</UserByte2>
        <Resolution>12</Resolution>
        <PowerSource>255</PowerSource>
    </owd_DS18B20>  
</Devices-Detail-Response>]]>.Value

    m_xmld = New XmlDocument()
    m_xmld.LoadXml(xml)
    'Dim m_xmlns As New XmlNamespaceManager(m_xmld.NameTable)
    'm_xmlns.AddNamespace("opsm_ns", "http://tempuri.org/zitem.xsd")
    Dim deviceId As String = "2D0000023C519A28"

    For Each node As XmlNode In m_xmld.SelectNodes("//owd_DS18B20/ROMId[text()='" & deviceId & "']/../Temperature")
        node.InnerText.Dump()
    Next

End Sub

Update 2 - This works. Your XML is missing closing tag for </HostName>. You will also have to specify namespace for every tag along the XPath.

 //opsm_ns:owd_DS18B20/opsm_ns:ROMId[text()='" & deviceId & "']/../opsm_ns:Temperature

Here is the whole mini-program.

Sub Main
    Dim xml As String
    Dim m_xmld As XmlDocument

    xml = <![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Devices-Detail-Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.embeddeddatasystems.com/schema/owserver">
<PollCount>150722</PollCount>
<DevicesConnected>4</DevicesConnected>
<LoopTime>3.974</LoopTime>
<DataErrors>2</DataErrors>
<DeviceName>OW_SERVER-Enet</DeviceName>
<HostName>EDSOWSERVER</HostName>
<MACAddress>00:50:C2:91:B3:9C</MACAddress>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>2D0000023C519A28</ROMId>
<Health>7</Health>
<RawData>0E014B467FFF021000000</RawData>
<PrimaryValue>16.8750 Deg C</PrimaryValue>
<Temperature Units="Centigrade">16.8750</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>0</PowerSource>
</owd_DS18B20>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>DA000002E0E5A928</ROMId>
<Health>7</Health>
<RawData>32014B467FFF0E101E000000</RawData>
<PrimaryValue>19.1250 Deg C</PrimaryValue>
<Temperature Units="Centigrade">19.1250</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>0</PowerSource>
</owd_DS18B20>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>C3000002E0EE1B28</ROMId>
<Health>7</Health>
<RawData>1D014B467FFF0310C5000000</RawData>
<PrimaryValue>17.8125 Deg C</PrimaryValue>
<Temperature Units="Centigrade">17.8125</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>0</PowerSource>
</owd_DS18B20>
<owd_DS18B20 Description="Programmable resolution thermometer">
<Name>DS18B20</Name>
<Family>28</Family>
<ROMId>070000023DBB7F28</ROMId>
<Health>7</Health>
<RawData>52014B467FFF0E10FFFF0000000000000000</RawData>
<PrimaryValue>21.1250 Deg C</PrimaryValue>
<Temperature Units="Centigrade">21.1250</Temperature>
<UserByte1 Writable="True">75</UserByte1>
<UserByte2 Writable="True">70</UserByte2>
<Resolution>12</Resolution>
<PowerSource>255</PowerSource>
</owd_DS18B20>
</Devices-Detail-Response>]]>.Value

    m_xmld = New XmlDocument()
    m_xmld.LoadXml(xml)
    Dim m_xmlns As New XmlNamespaceManager(m_xmld.NameTable)
    m_xmlns.AddNamespace("opsm_ns", "http://www.embeddeddatasystems.com/schema/owserver")
    Dim deviceId As String = "2D0000023C519A28"

    For Each node As XmlNode In m_xmld.SelectNodes("//opsm_ns:owd_DS18B20/opsm_ns:ROMId[text()='" & deviceId & "']/../opsm_ns:Temperature", m_xmlns)
        node.InnerText.Dump()
    Next

End Sub

Upvotes: 2

Dan Field
Dan Field

Reputation: 21641

Your XML is in the default namespace, but you're attempting to read nodes that are in a specified namespace. Change this:

m_xmld = New XmlDocument()
m_xmld.Load("http://" & server_ip & "/details.xml")
Dim m_xmlns As New XmlNamespaceManager(m_xmld.NameTable)
m_xmlns.AddNamespace("opsm_ns", "http://tempuri.org/zitem.xsd")

For Each node As XmlNode In
m_xmld.SelectNodes("//opsm_ns:owd_DS18B20[ROMId='" & deviceId & "']",m_xmlns)
Console.WriteLine(node.Attributes("Temperature").Value)
Next

to this:

m_xmld = New XmlDocument()
m_xmld.Load("http://" & server_ip & "/details.xml")
/* Dim m_xmlns As New XmlNamespaceManager(m_xmld.NameTable)
m_xmlns.AddNamespace("opsm_ns", "http://tempuri.org/zitem.xsd") */

For Each node As XmlNode In
m_xmld.SelectNodes("//owd_DS18B20[ROMId='" & deviceId & "']") /*,m_xmlns)*/
Console.WriteLine(node.Attributes("Temperature").Value)
Next

Or, using your new update, which is in a namespace (but different from what you were actually using, you could do this):

m_xmld = New XmlDocument()
m_xmld.Load("http://" & server_ip & "/details.xml")
Dim m_xmlns As New XmlNamespaceManager(m_xmld.NameTable)
m_xmlns.AddNamespace("opsm_ns", "http://www.embeddeddatasystems.com/schema/owserver")

For Each node As XmlNode In
m_xmld.SelectNodes("//opsm_ns:owd_DS18B20[ROMId='" & deviceId & "']",m_xmlns)
Console.WriteLine(node.Attributes("Temperature").Value)
Next

If it turns out that your XML does actually contain namespaces in some instances but not others, but you know you always want that node by name, you could use the local-name() function like so:

m_xmld.SelectNodes("//*[local-name()='owd_DS18B20'][ROMId='" & deviceId & "']")

Upvotes: 2

Related Questions