XPath没有返回节点值ASP.NET 4.5

时间:2016-02-24 13:38:22

标签: asp.net xml vb.net xpath

这里有一个小问题,我正在为客户转换传统的经典ASP应用程序到ASP.NET 4.5,并且需要从XML文件中提取数据,但是我无法获得单个节点的价值,我的代码只返回任何内容。

XML文件

<?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>

我需要能够根据ROMId获取温度值,因为任何时候最多可以连接22个传感器。

我尝试过以下但是它总是没有任何结果:

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

文档加载但我无法获取数据,因为没有返回任何内容,我在这里缺少什么?

提前致谢

奥奇

更新2:已在Visual Studio中获取完整的XML输出并在上面更新

更新3:使用上面的@CrnaStena中的示例,并且仍然没有返回任何值

2 个答案:

答案 0 :(得分:2)

所以这是我在C#中的LinqPad示例,抱歉我在20年内没有使用过VB。我已经扩展了您的XML以添加具有不同ROMid和温度的其他节点。

../AcapelaLibs/libbabile.a

结果显示.pro

更新1

我刷了VB,这里是LinqPad VB代码,结果相同:

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();
    }


}

更新2 - 这有效。您的XML缺少22.0625的结束标记。您还必须为XPath中的每个标记指定名称空间。

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

这是整个迷你程序。

</HostName>

答案 1 :(得分:2)

您的XML位于默认命名空间中,但您正在尝试读取指定命名空间中的节点。改变这个:

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

到此:

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

或者,使用位于命名空间中的新更新(但与您实际使用的更新不同,您可以执行此操作):

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

如果事实证明你的XML在某些情况下实际上包含名称空间而不是其他实例,但是你知道你总是希望按名称使用该节点,你可以使用local-name()函数,如下所示:

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