2012-02-14 60 views
2

我有以下格式XPath表達式爲不特定屬性

<someXML> 
    <a> 
     <b></b> 
     <b test='someValue'></b> 
    </a> 

    <c> 
     <d test='someOtherValue'></d> 
     <d></d> 
    </c> 
</someXML> 

我試着寫C#代碼,將讓我只包含與那些節點的節點集的XML文件中查找一個元素測試屬性。我試圖以這種方式使用XPathExpression:

XDocument document = XDocument.Load("someXML"); 
XPathNavigator navigator = document.CreateNavigator(); 
XPathExpression expression = XPathExpression.Compile("//*[@test]"); 
object nodeSet = navigator.Evaluate(expression); 

這似乎不工作。當我調試時,nodeSet總是包含Root元素。表達有什麼問題或者這個工作是否正確?

謝謝!

回答

3

您是否假設nodeSet包含「根」元素,因爲調試器顯示其字符串表示形式爲Position=0, Current={Root}?這可能是誤導性的;出現「Root」元素的原因是因爲XPathNodeIterator(這是您的案例中由Evaluate返回的實際類型)尚未定位在查詢產生的第一個節點上。每MSDN文檔XPathNodeIterator

XPathNavigator類返回一個XPathNodeIterator對象不位於選定的一組節點的第一個節點上。必須調用MoveNext方法的XPathNodeIterator類來將XPathNodeIterator對象定位到所選節點集合中的第一個節點上。

您可以通過遍歷您nodeSet檢索您的路徑項目:

XDocument document = XDocument.Load("someXML"); 
XPathNavigator navigator = document.CreateNavigator(); 
XPathExpression expression = XPathExpression.Compile("//*[@test]"); 
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(expression); 
foreach (XPathItem item in nodeSet) 
{ 
    // Process item here 
} 

或者,如果你希望他們轉換爲一個數組:

XDocument document = XDocument.Load("someXML"); 
XPathNavigator navigator = document.CreateNavigator(); 
XPathExpression expression = XPathExpression.Compile("//*[@test]"); 
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(expression); 
XPathItem[] items = nodeSet.Cast<XPathItem>().ToArray(); 
+0

糟糕!你是對的!我假設。謝謝!! :) – 2012-02-14 19:51:26

4

你的XPath 不工作,這只是你需要檢索節點有點不同:

XPathNavigator navigator = document.CreateNavigator(); 
XPathExpression expression = XPathExpression.Compile("//*[@test]"); 
var matchedNodes = navigator.Select(expression); 
foreach (XPathNavigator node in matchedNodes) 
{ 
    Console.WriteLine(node.UnderlyingObject); 
} 

摘錄上面會打印以下:

<b test='someValue'></b> 
<d test='someOtherValue'></d> 
1

我相信你會想使用XPathNavigator對象的選擇方法,而不是評估,這將返回創建XPathNodeIterator對象。

http://msdn.microsoft.com/en-us/library/3tk3f03k.aspx

,或者您可以使用XmlDocument對象和XmlNodeList中:

 XmlDocument document = new XmlDocument(); 
     document.Load("somexml.xml"); 

     XmlNodeList nodeList = document.SelectNodes("//*[@test]"); 

     foreach (XmlNode Node in nodeList) { 
      // do something.    
     } 
3

你的表情似乎是正確的。但是你可以使用XPathSelectElements擴展方法來simplier做到這一點:

var nodes = document.XPathSelectElements("//*[@test]"); 
0

爲什麼不只是這樣做,假設你只是想節點和別有一番特別原因需要使用導航(空檢查省略掉):

var document = XDocument.Load("someXML"); 
var myNodes = document.Descendants().Where(node => node.Attribute(myAttributeName) != null); 

它不使用導航器,但它非常簡單直接,如果你只是想要的節點。

2

您的XPath查詢是正確的。當前成員將是根元素(我不是XPathIterator專家,所以我不知道它背後的基本原理)。如果您遍歷NodeSet,則只會獲得與XPath查詢匹配的內容。所以我想答案是迭代集合並將每個項目放入一個集合中。