2013-06-01 40 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