2013-06-01 17 views
1

Folks ....这是我最近询问的一个类似问题的后续。如何从XML结构中检索特定的值,而不必沿着结构遍历并遍历所有的子节点?有人建议我应该使用XPath。在ASP页面中处理XML - 第2部分

假设以下简单的XML结构:

<MyWeather> 
    <sensor location="Front Entry"> 
    <reading label="Temperature"> 
     <title>Front Entry</title> 
     <label>Temperature</label> 
     <value>54</value> 
     <units>F</units> 
     <lastUpdate>05/27/2013 12:23 AM</lastUpdate> 
    </reading> 
    <reading label="Humidity"> 
     <title>Front Entry</title> 
     <label>Humidity</label> 
     <value>66</value> 
     <units>%</units> 
     <lastUpdate>05/27/2013 12:23 AM</lastUpdate> 
    </reading> 
</sensor> 
<sensor location="Patio"> 
    <reading label="Temperature"> 
     <title>Patio</title> 
     <label>Temperature</label> 
     <value>46</value> 
     <units>F</units> 
     <lastUpdate>05/27/2013 12:23 AM</lastUpdate> 
    </reading> 
    <reading label="Humidity"> 
     <title>Patio</title> 
     <label>Humidity</label> 
     <value>93</value> 
     <units>%</units> 
     <lastUpdate>05/27/2013 12:23 AM</lastUpdate> 
    </reading> 

    </sensor> 
</MyWeather> 

这里是我的ASP页面的一部分:

<% 
xmlDoc = CreateObject("Msxml2.DOMDocument") 
xmldoc.setProperty ("ServerHTTPRequest", true) 
xmlDoc.setProperty ("ProhibitDTD", False) 
xmlDoc.validateOnParse = true 

' Filename is a sting variable containing the URL 

xmlDoc.async = "False" 
xmlDoc.load(FileName) 

' Error and return code processing done here but removed 

For Each el In xmldoc.childNodes 
    if el.childnodes.length <> 0 then 
    response.write ("<table align='center' class='auto-style1'>") 
    for each el2 in el.childnodes 
     Response.write("<tr><td>" & el2.getattribute("location") & "</td><td></td></tr>") 
     for each el3 in el2.childnodes 
      for each el4 in el3.childnodes 
      if el4.nodename = "value" then 
      Response.write("<tr><td></td><td>" & el3.getattribute("label") & " " & el4.text & " " & el4.nextSibling.text & "</td></tr>") 
      exit for 
       end if 
      next 
      next 
     next 
    response.write ("</table>") 
    end if 
    Next 
xmlDoc = Nothing 

%> 

我的问题是关于在“的代码对于每个EL4 ...“部分。你会发现我遍历了子节点,直到找到“值”。然后我输出该标签值,并且,因为我知道下一个标签(现在直到他们改变它),所以我使用nextposition来获取该值。 此代码有效!

我想知道的是: 有没有更直接的方式来为传感器位置阅读标签的任意组合这两个变量值没有我的迭代过程。

我有几个其他情况下,我可能需要遍历50多个元素来找到我正在寻找的标签。

我添加了这个xPath代码,基于我之前的问题的建议。这一点,如果它的工作将取代“每个EL4在el3.childnodes环”上述

xmlDoc.setProperty ("SelectionLanguage", "XPath") 

       oNode = xmldoc.selectSingleNode("//reading[@label='Temperaure']/units") 
       o2Node = xmldoc.selectSingleNode("//reading[@label='Temperaure']/value") 
       if oNode is nothing or o2node is nothing then 
        Response.write("<tr><td></td><td> Nothing found for value or units </td><td>" & el3.getattribute("label") & "</tr>") 
        else 
        Response.write("<tr><td></td><td>" & el3.getattribute("label") & " " & o2Node.text & " " & oNode.text & "</td></tr>") 
        end if  

但是,它并没有为我工作。我尝试了几个变种:​​没有@符号和oNode语句中的完整路径,即/ MyWeather/sensor/reading/...

我对空的oNode和/或O2Node的检查总是如此。

任何想法?..... RDK

+1

你真的上查询“Temperaure”?那么你最好修复这个错字。 –

回答

0

如果你已经走过的树,然后用所有的嵌套循环For Each有点替换进一步,你需要确保嵌套For Each您呼吁的selectSingleNode变量在外部For Each和你使用相对路径例如

Response.Write el3.selectSingleNode("value").text 

我强烈建议不要使用在所有的childNodes而只是为了确保您使用selectNodes与你感兴趣的元素的路径,这样,它是更清楚哪个元素节点正在处理;例如,如果你真的检查XML输入已与当时的错误检查

For Each el In xmldoc.childNodes 
    if el.childnodes.length <> 0 then 
    response.write ("<table align='center' class='auto-style1'>") 

是多余的,因为一个良好的XML文档总是有一个根元素的子节点,以便一旦你已经检查如成功解析

If xmlDoc.parseError.errorCode = 0 Then 
    Response.Write ("<table align='center' class='auto-style1'>") 

应该就足够了。

如果您然后想要访问根元素(在您的情况下,MyWheater元素)就可以使用xmlDoc.documentElement

而且你可以再使用

For Each sensor In xmlDoc.documentElement.selectNodes("sensor") 
    Dim tr 
    Set tr = sensor.selectSingleNode("reading[@label = 'Temperature']") 
    Response.Write tr.selectSingleNode("value").text & " " & tr.selectSingleNode("unit").text 
    Next 

与XML唯一的疑难杂症是命名空间,如果你真正的XML有一个像xmlns="http://example.com"或者任何DTD属性,你有套这样的属性为默认值,然后用MSXML你需要使用例如

xmlDoc.setProperty "SelectionNamespaces", "xmlns:df='http://example.com'" 

,并进一步对您需要使用的前缀(例如df)有资格在你的XPath表达式元素名称传递给selectNodesselectSingleNode

For Each sensor In xmlDoc.documentElement.selectNodes("df:sensor") 
    Dim tr 
    Set tr = sensor.selectSingleNode("df:reading[@label = 'Temperature']") 
    Response.Write tr.selectSingleNode("df:value").text & " " & tr.selectSingleNode("df:unit").text 
    Next 
+0

哇!感谢您提供详细且有据可查的回复。我印象深刻。不幸的是,我即将离开几天,所以我不会马上学习和应用你的建议。当我尝试过它们时,我会回来。再次感谢。 – RDK

+0

Martin .....再次感谢您的回复。我研究了你的意见,并成功地将它们应用于我的项目。再次赞扬。 我还需要感谢Jens Erat捕捉我的错字,这肯定会导致我以前的一些问题。 – RDK